Так как давно хотел пощупать GCP и неплохо было бы освежить знания о kubernetes, решил объединить эти задачки и заодно написать статью. Вместо k8s GCP (GKE) можно использовать minikube или куб в Docker Desctop. Ну а мы идём в GCP.
Аккаунтом GCP я уже пользовался, поэтому все необходимые сервисы включены, а права на локальной машине получены. Если Вы будете использовать для тестов локальный кубер, таких проблем вообще не возникнет.
Для начала создам k8s кластер и пул машин, на которых будем гонять тесты. Для этого нужно найти слова Kubernetes Engine в панели GCP и нажать на пару кнопок. Как на скринах ниже.
На скрине выше видна кнопочка Connect. Нажав её можно узнать команду для подключения к кластеру через gcloud. У меня было так
gcloud container clusters get-credentials wordpress --zone europe-north1-a --project test-gke-and-etc
Fetching cluster endpoint and auth data.
kubeconfig entry generated for wordpress.
Отлично, проверим.
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-desktop docker-desktop docker-desktop
* gke_test-gke-and-etc_europe-north1-a_wordpress gke_test-gke-and-etc_europe-north1-a_wordpress gke_test-gke-and-etc_europe-north1-a_wordpress
minikube minikube minikube
Вроде все как надо. Начинаем самое интересное. План такой:
— сделаем mysql
— поднимем контейнер с apache-php
— настроем loadbalancer
— установим wordpress
Mysql установим как советует нам дока. mysql.yml:
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
# Use secret in real usage
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
Тут мы создаём деплой mysql и заодно вытарчиваем с него 3306 порт, который будет доступен только внутри кластера.
Но перед этим надо создать Persistent Volume. Сделаю сразу все что понадобиться. pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: site-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Наконец применяем и смотрим что получилось:
kubectl apply -f pvc.yaml
persistentvolumeclaim/mysql-pv-claim created
persistentvolumeclaim/site-data created
kubectl apply -f mysql.yaml
service/mysql created
deployment.apps/mysql created
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pv-claim Bound pvc-d28125b3-4e36-45df-b260-ace8a5b87331 10Gi RWO standard 34s
site-data Bound pvc-25cc890f-0330-4091-ab69-5dcc8de0db9b 10Gi RWO standard 34s
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
mysql 1/1 1 1 41s
Чтобы зайти в mysql и создать там БД поднимем контейнер. Все из той же доки:
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
If you don't see a command prompt, try pressing enter.
mysql> create database wordpress;
Query OK, 1 row affected (0.00 sec)
Класс! Mysql уже есть. Как создать юзера. Теперь нам нужен веб сервер и php. Так как я не смог найти ничего, что можно прямо с докерхаба забрать, придётся сделать контейнер самостоятельно. Dockerfile:
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install apache2 -y && \
apt install php php-mysql -y
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
Попробуем Container Registry, которое предоставляет нам Гугл. Так как я уже ходил в него, вопросов с доступом не возникнет, но в первый раз docker push не даст доступа, но предоставит ссылочку на инструкцию. В общем делаем как сказано в инструкции:
docker build -t gcr.io/test-gke-and-etc/apache-php .
docker push gcr.io/test-gke-and-etc/apache-php
apiVersion: v1
kind: ConfigMap
metadata:
name: siteconfig
data:
000-default.conf: |
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/site
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Применяем:
kubectl apply -f configmap.yaml
configmap/siteconfig created
Теперь деплой apache и php. apache-php.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
labels:
app: web-server
spec:
replicas: 1
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
spec:
containers:
- name: apache-php
image: gcr.io/test-gke-and-etc/apache-php:latest
ports:
- containerPort: 80
volumeMounts:
- name: site-data-pvc
mountPath: /var/www/site
- name: siteconfig
mountPath: /etc/apache2/sites-available/000-default.conf
subPath: 000-default.conf
volumes:
- name: site-data-pvc
persistentVolumeClaim:
claimName: site-data
- name: siteconfig
configMap:
name: siteconfig
kubectl apply -f apache-php.yaml
deployment.apps/web-server created
Посмотрим что есть на текущий момент:
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/mysql-68579b78bb-2btj9 1/1 Running 0 17m
pod/web-server-6bdcd547d7-jxz2s 1/1 Running 0 27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.4.0.1 <none> 443/TCP 37m
service/mysql ClusterIP None <none> 3306/TCP 17m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql 1/1 1 1 17m
deployment.apps/web-server 1/1 1 1 27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/mysql-68579b78bb 1 1 1 17m
replicaset.apps/web-server-6bdcd547d7 1 1 1 27s
kubectl get configmaps
NAME DATA AGE
kube-root-ca.crt 1 37m
siteconfig 1 4m20s
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pv-claim Bound pvc-d28125b3-4e36-45df-b260-ace8a5b87331 10Gi RWO standard 18m
site-data Bound pvc-25cc890f-0330-4091-ab69-5dcc8de0db9b 10Gi RWO standard 18m
Если у Вас что-то выглядет не так, возможно следует начать сначала 🙂
Сделаем лоадбалансер. Это можно провернуть только в клауде. loadbalanser.yaml:
apiVersion: v1
kind: Service
metadata:
name: lb
spec:
selector:
app: web-server
ports:
- port: 80
targetPort: 80
type: LoadBalancer
kubectl apply -f loadbalanser.yaml
service/lb created
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.4.0.1 <none> 443/TCP 40m
lb LoadBalancer 10.4.1.189 <pending> 80:30533/TCP 24s
mysql ClusterIP None <none> 3306/TCP 20m
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.4.0.1 <none> 443/TCP 42m
lb LoadBalancer 10.4.1.189 34.88.201.224 80:30533/TCP 98s
mysql ClusterIP None <none> 3306/TCP 22m
Подождав немного можно увидеть IP-адрес lb. На него уже можно сходить в браузере и увидеть что в папке сайта ничего нет.
Скачаем wordpress с офф сайта, распакуем и копируем в контейнер:
kubectl cp wordpress web-server-6bdcd547d7-jxz2s:/var/www/site
Далее я зашел в контейнер, поправил права и перемести файлы wordpress в корень persistent volume.
kubectl exec -it web-server-6bdcd547d7-jxz2s -- bash
cd /var/www/site/
chown 33:33 -R /var/www/site/
mv wordpress/* ./
rm -rf wordpress/
Ну а теперь наконец идем на LB и устанавливаем wordpress.