Kubernetes容器化工具Kind實踐部署Kubernetes v1.18.x 版本, 釋出WordPress和MySQL

PassZhang發表於2020-07-14

Kind 介紹

Kind是Kubernetes In Docker的縮寫,顧名思義是使用Docker容器作為Node並將Kubernetes部署至其中的一個工具。官方文件中也把Kind作為一種本地叢集搭建的工具進行推薦。預設情況下,Kind會先下載kindest/node映象,該映象包含kubernetes的主要元件,當映象節點準備好時,Kind使用kubeadm進行叢集的建立,內部使用containerd跑元件容器。最終,Kind只是為了方便測試kubernetes叢集的,且不可用於生產環境。

部署Kind

Kind使用Golang進行開發,在倉庫的Release頁面,已經上傳了構建好的二進位制,支援多種作業系統,可直接按需下載進行使用。

wget -O /usr/local/bin/kind https://github.com/kubernetes-sigs/kind/releases/download/v0.8.1/kind-linux-amd64 && chmod +x /usr/local/bin/kind

# kind v0.8.1版本支援最新kubernetes v1.18.2叢集

安裝docker

yum-config-manager --add-repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
sed -i 's#download.docker.com#mirrors.ustc.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo
yum install -y docker-ce

部署kubectl

wget -O /usr/local/bin/kubctl https://storage.googleapis.com/kubernetes-release/release/v1.18.5/bin/linux/amd64/kubectl
chmod +x /usr/local/bin/kubectl

建立kind單叢集

使用kind命令建立

使用kind create 建立叢集,預設是單節點叢集。

# kind create cluster --name test
Creating cluster "test" ...
 ✓ Ensuring node image (kindest/node:v1.18.2) 
 ✓ Preparing nodes 
 ✓ Creating kubeadm config 
 ✓ Starting control-plane ️ 
 ✓ Installing CNI 
 ✓ Installing StorageClass 

Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="test")"
kubectl cluster-info

在docker環境下,會啟動一個映象

CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS                                                                      NAMES
2e0a5e15a4a0        kindest/node:v1.18.2               "/usr/local/bin/entr…"   14 minutes ago      Up 14 minutes       45319/tcp, 127.0.0.1:45319->6443/tcp    test-control-plane

檢視叢集資訊

export KUBECONFIG="$(kind get kubeconfig-path --name="test")"
echo 'export KUBECONFIG="$(kind get kubeconfig-path --name=test)"' >> /root/.bashrc


kubectl cluster-info
Kubernetes master is running at https://localhost:45319
KubeDNS is running at https://localhost:45319/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

kubectl get node -o wide
NAME                 STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                                  KERNEL-VERSION          CONTAINER-RUNTIME
test-control-plane   Ready    master   16m   v1.18.2   172.17.0.2    <none>        Ubuntu Disco Dingo (development branch)   3.10.0-693.el7.x86_64   containerd://1.2.6-0ubuntu1

kubectl get pods --all-namespaces
NAMESPACE     NAME                                         READY   STATUS    RESTARTS   AGE
kube-system   coredns-fb8b8dccf-6r58d                      1/1     Running   0          17m
kube-system   coredns-fb8b8dccf-bntk8                      1/1     Running   0          17m
kube-system   etcd-test-control-plane                      1/1     Running   0          17m
kube-system   ip-masq-agent-qww8n                          1/1     Running   0          17m
kube-system   kindnet-vbz6w                                1/1     Running   0          17m
kube-system   kube-apiserver-test-control-plane            1/1     Running   0          16m
kube-system   kube-controller-manager-test-control-plane   1/1     Running   0          17m
kube-system   kube-proxy-wf7dq                             1/1     Running   0          17m
kube-system   kube-scheduler-test-control-plane            1/1     Running   0          16m

啟動nginx app

kubectl run nginx --image nginx:1.17.0-alpine --restart=Never --port 80 --labels="app=nginx-test"

kubectl port-forward --address 0.0.0.0 pod/nginx 8080:80
curl localhost:8080

指定配置檔案建立

# cat kube-config.yaml
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
kubeadmConfigPatches:
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: ClusterConfiguration
  metadata:
    name: config
  networking:
    serviceSubnet: 10.0.0.0/16
  imageRepository: registry.aliyuncs.com/google_containers
  nodeRegistration:
    kubeletExtraArgs:
      pod-infra-container-image: registry.aliyuncs.com/google_containers/pause:3.1
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: InitConfiguration
  metadata:
    name: config
  networking:
    serviceSubnet: 10.0.0.0/16
  imageRepository: registry.aliyuncs.com/google_containers
nodes:  # 指定節點,預設是一個節點
- role: control-plane

# kind create cluster --name test2 --config kube-config.yaml
Creating cluster "test2" ...
 ✓ Ensuring node image (kindest/node:v1.18.2) 
 ✓ Preparing nodes 
 ✓ Creating kubeadm config 
 ✓ Starting control-plane ️ 
 ✓ Installing CNI 
 ✓ Installing StorageClass 
                            Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="test2")"
kubectl cluster-info

建立kind-ha叢集

只能通過配置檔案來宣告ha叢集配置

# cat kind-ha-config.yaml
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
kubeadmConfigPatches:
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: ClusterConfiguration
  metadata:
    name: config
  networking:
    serviceSubnet: 10.0.0.0/16
  imageRepository: registry.aliyuncs.com/google_containers
  nodeRegistration:
    kubeletExtraArgs:
      pod-infra-container-image: registry.aliyuncs.com/google_containers/pause:3.1
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: InitConfiguration
  metadata:
    name: config
  networking:
    serviceSubnet: 10.0.0.0/16
  imageRepository: registry.aliyuncs.com/google_containers
nodes:  #主要修改這個位置,增加role,指定node節點,工作節點名稱必須為worker,master節點必須為control-plane
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker

# kind create cluster --name test-ha --config kind-ha-config.yaml
Creating cluster "test-ha" ...
 ✓ Ensuring node image (kindest/node:v1.18.2) 
 ✓ Preparing nodes 
 ✓ Configuring the external load balancer ⚖️ 
 ✓ Creating kubeadm config 
 ✓ Starting control-plane ️ 
 ✓ Installing CNI 
 ✓ Installing StorageClass 
 ✓ Joining more control-plane nodes 
 ✓ Joining worker nodes 

                         Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="test3")"
kubectl cluster-info


# kubectl get nodes
NAME                   STATUS   ROLES    AGE     VERSION
test3-control-plane    Ready    master   7m44s   v1.18.2
test3-control-plane2   Ready    master   4m59s   v1.18.2
test3-control-plane3   Ready    master   2m18s   v1.15.0
test3-worker           Ready    <none>   110s    v1.15.0
test3-worker2          Ready    <none>   109s    v1.15.0
test3-worker3          Ready    <none>   105s    v1.15.0

常用操作

kind 是基於 docker 的,那麼我們再來看下 docker 資源,來驗證一下是否真的是基於 docker 的?

# 本機執行,就會提示有個docker容器正在執行,可以看到 docker 裡有一個 container,而 kind 建立的叢集就是基於這個 container 的,如果你直接刪掉了這個 container,通過 kind 建立的 k8s 叢集也會有問題

docker ps
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS                                                                      NAMES
2e0a5e15a4a0        kindest/node:v1.18.2               "/usr/local/bin/entr…"   14 minutes ago      Up 14 minutes       45319/tcp, 127.0.0.1:45319->6443/tcp    test-control-plane

再來看一下 network,執行 docker network ls,可以看到有一個名稱為 kind 的 network。

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
94de31154cb7        bridge              bridge              local
0c31de104d44        host                host                local
a667b873436d        kind                bridge              local
6083dbc308a4        none                null                local

我們可以進一步探究 kind-control-plane(就是上面的 docker container)

通過 docker exec kind-control-plane crictl ps 獲取這個容器內部的執行容器列表,這個容器內部通過 crictl 來操作容器,可以參考 https://github.com/kubernetes-sigs/cri-tools,crtctl 主要用來管理容器,命令使用和docker命令是一樣,可以通過 docker exec kind-control-plane crictl help 幫助檢視命令使用方法。

# master 節點
docker exec kind-ha-control-plane crictl ps
CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID
4b62cd954c86a       ace0a8c17ba90       18 minutes ago      Running             kube-controller-manager   3                   8f000bb1c20f3
90552a29c50d9       db10073a6f829       19 minutes ago      Running             local-path-provisioner    8                   7e648bc7297b1
268f41443c426       a3099161e1375       19 minutes ago      Running             kube-scheduler            4                   a64377f98d627
aa3fea2edc80d       67da37a9a360e       3 hours ago         Running             coredns                   0                   719884414c5f4
04c58978f5395       67da37a9a360e       3 hours ago         Running             coredns                   0                   da6e08629ac71
110429a5a873b       2186a1a396deb       3 hours ago         Running             kindnet-cni               0                   5359903320ef9
1c125b02f6300       0d40868643c69       3 hours ago         Running             kube-proxy                0                   9ba4d0a1fdd3d
0301cd4d26d9c       6ed75ad404bdd       3 hours ago         Running             kube-apiserver            0                   4905e2b2a8a1a
435ee12a45bff       303ce5db0e90d       3 hours ago         Running             etcd                      0                   96f4e9190bede

# worker節點
docker exec kind-ha-worker crictl ps
CONTAINER           IMAGE               CREATED             STATE               NAME                ATTEMPT             POD ID
5e82bf4756b6f       bfba26ca350c1       21 minutes ago      Running             nginx               0                   78d1324b8b1a1
ea02b20040341       0d40868643c69       3 hours ago         Running             kube-proxy          0                   de6a57d0b7381
c2aa986df532f       2186a1a396deb       3 hours ago         Running             kindnet-cni         1                   ebea7a329cfe0

獲取 k8s 叢集所有資源示例

kubectl get all --all-namespaces

獲取叢集外部的config配置配置檔案

kind  get kubeconfig --name kind-ha

獲取叢集內部的config配置配置檔案(一般獲取外部就夠用了)

kind  get kubeconfig --internal --name kind-ha

刪除叢集(清理很方便)

kind delete cluster --name test

掛載檔案

nodes:
- role: control-plane
  extraMounts:
    - containerPath: /etc/docker/daemon.json
      hostPath: /etc/docker/daemon.json
      readOnly: true

暴露埠方法1

nodes:
- role: control-plane
  extraPortMappings:
    - containerPort: 30080
      hostPort: 30080

有時候我們想暴露svc的埠給外部訪問,因為kubernetes的節點是在docker容器中,所以還需要容器暴露svc的埠,外部才能通過宿主機訪問。

暴露埠方法2

# 使用埠轉發的方式

kubectl port-forward --address 0.0.0.0 pod/nginx 8080:80

從私有倉庫下載映象

docker exec test-drone-control-plane bash -c "sed -i '56a\        [plugins.cri.registry.mirrors.\"192.168.77.134:5000\"]' /etc/containerd/config.toml" 
docker exec test-drone-control-plane bash -c "sed -i '57a\          endpoint = [\"http://192.168.77.134:5000\"]' /etc/containerd/config.toml" 
docker exec test-drone-control-plane bash -c "cat /etc/containerd/config.toml"
docker exec test-drone-control-plane bash -c 'kill -s SIGHUP $(pgrep containerd)'
COPY

還可以通過掛載檔案的方式,掛載containerd的配置檔案

重啟叢集

docker stop test-drone-control-plane
docker start test-drone-control-plane
COPY

總之,kind可以很方便的在docker環境下建立測試叢集,而不汙染我們的宿主機,給我們測試提供了很大的便利。

示例:使用持久卷部署WordPress和MySQL

本教程向您展示如何使用Kind部署WordPress網站和MySQL資料庫。這兩個應用程式都使用PersistentVolumes和PersistentVolumeClaims來儲存資料。

PersistentVolume(PV)是已經由管理員手動供應,或動態地使用由Kubernetes置備叢集中的一塊儲存的StorageClassPersistentVolumeClaim(PVC)是由能夠由PV滿足使用者對於儲存的請求。PersistentVolumes和PersistentVolumeClaims與Pod生命週期無關,並通過重新啟動,重新計劃甚至刪除Pod來保留資料。

警告:此部署不適合生產用例,因為它使用單例項WordPress和MySQL Pods。考慮使用WordPress Helm Chart在生產中部署WordPress。

注意:本教程中提供的檔案使用的是GA Deployment API,並且特定於kubernetes 1.9和更高版本。如果您希望將本教程與Kubernetes的早期版本一起使用,請相應地更新API版本,或參考本教程的早期版本。

目標

  • 建立PersistentVolumeClaims和PersistentVolumes
  • 建立一個kustomization.yaml
    • Secret密碼配置
    • MySQL資源配置
    • WordPress資源配置
  • 通過以下方式應用Kustomization目錄 kubectl apply -k ./
  • 清理

在你開始之前

您需要具有Kubernetes叢集,並且必須將kubectl命令列工具配置為與叢集通訊。如果還沒有叢集,則可以使用Minikube或者是Kind建立一個叢集,也 可以使用以下Kubernetes遊樂場之一:

要檢查版本,請輸入kubectl version。此頁面上顯示的示例適用於kubectl1.14及更高版本,上面我們已經建立了kind-ha叢集,直接執行後面的步驟既可。

kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", BuildDate:"2020-04-16T11:48:36Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

下載以下配置檔案:

  1. mysql-deployment.yaml
  2. wordpress-deployment.yaml

建立PersistentVolumeClaims和PersistentVolumes

MySQL和Wordpress都需要一個PersistentVolume來儲存資料。他們的PersistentVolumeClaims將在部署步驟中建立。

許多叢集環境都安裝了預設的StorageClass。如果在PersistentVolumeClaim中未指定StorageClass,則使用群集的預設StorageClass。

建立PersistentVolumeClaim後,將根據StorageClass配置動態設定PersistentVolume。

# 檢視StorageClass
kubectl get sc

kubectl describe  sc $(kubectl get sc |grep default|awk 'NR==2{print $1}')

警告:在本地叢集中,預設的StorageClass使用hostPath配置程式。hostPath該卷僅適用於開發和測試。有了hostPath卷,您的資料/tmp將駐留在Pod排程到的節點上,並且不會在節點之間移動。如果Pod死亡並被排程到群集中的另一個節點,或者該節點被重新引導,則資料將丟失。

注意:如果要啟動需要使用hostPath配置程式的群集,則--enable-hostpath-provisioner必須在controller-manager元件中設定該標誌。

注意:如果您有一個在Kubernetes Engine上執行的Kubernetes叢集,請遵循本指南

建立一個Secret密碼檔案kustomization.yaml

secret是一個物件,其儲存了一塊如密碼或金鑰的敏感資料。從1.14開始,kubectl支援使用kustomization檔案管理Kubernetes物件。您可以通過中的生成器建立Secret kustomization.yaml

kustomization.yaml從以下命令中新增一個Secret生成器。您將需要替換YOUR_PASSWORD為您要使用的密碼。

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
  literals:
  - password=YOUR_PASSWORD
EOF

為MySQL和WordPress新增資源配置

以下清單描述了單例項MySQL部署。MySQL容器將PersistentVolume掛載在/ var / lib / mysql。在MYSQL_ROOT_PASSWORD環境變數設定從secret資料庫密碼。

application/wordpress/mysql-deployment.yaml

apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: 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

以下清單描述了單例項WordPress部署。WordPress容器將PersistentVolume安裝在/var/www/html用於網站資料檔案的位置。在WORDPRESS_DB_HOST環境變數設定上面定義的MySQL服務的名稱,WordPress會由服務訪問資料庫。在 WORDPRESS_DB_PASSWORD環境變數設定從生成的祕密kustomize資料庫密碼。

application/wordpress/wordpress-deployment.yaml

application/wordpress/wordpress-deployment.yaml 

apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:4.8-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

使用curl 命令直接下載配置檔案

  1. 下載MySQL部署配置檔案。

    curl -LO https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
    
  2. 下載WordPress配置檔案。

    curl -LO https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
    
  3. 將它們新增到kustomization.yaml檔案。

    cat <<EOF >>./kustomization.yaml
    resources:
      - mysql-deployment.yaml
      - wordpress-deployment.yaml
    EOF
    

執行並驗證

kustomization.yaml包含用於部署WordPress網站和MySQL資料庫的所有資源。您可以通過以下方式啟動應用

kubectl apply -k ./

現在,您可以驗證所有物件是否存在。

  1. 通過執行以下命令來驗證機密是否存在:

    kubectl get secrets
    

    響應應如下所示:

    NAME                    TYPE                                  DATA   AGE
    mysql-pass-c57bb4t7mf   Opaque                                1      9s
    
  2. 驗證是否已動態配置PersistentVolume。

    kubectl get pvc
    

    注意:設定和繫結PV可能要花費幾分鐘。

    響應應如下所示:

    NAME             STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
    mysql-pv-claim   Bound     pvc-8cbd7b2e-4044-11e9-b2bb-42010a800002   20Gi       RWO            standard           77s
    wp-pv-claim      Bound     pvc-8cd0df54-4044-11e9-b2bb-42010a800002   20Gi       RWO            standard           77s
    
  3. 通過執行以下命令來驗證Pod是否正在執行:

    kubectl get pods
    

    注意: Pod的狀態最多可能需要幾分鐘的時間RUNNING

    響應應如下所示:

    NAME                               READY     STATUS    RESTARTS   AGE
    wordpress-mysql-1894417608-x5dzt   1/1       Running   0          40s
    
  4. 通過執行以下命令來驗證服務是否正在執行:

    kubectl get services wordpress
    

    響應應如下所示:

    NAME        TYPE            CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    wordpress   LoadBalancer    10.0.0.89    <pending>     80:32406/TCP   4m
    

    注意: Minikube只能通過公開服務NodePort。EXTERNAL-IP始終處於掛起狀態。

    ​ 當前我使用的是kind建立叢集,可以直接通過埠轉發方式,進行訪問WordPress頁面

  5. 執行以下命令以獲取WordPress服務的IP地址:

    kubectl port-forword --address 0.0.0.0 svc/wordpress 8000:80 
    
  6. 複製IP地址,然後將頁面載入到瀏覽器中以檢視您的站點。

    您應該看到類似於以下螢幕截圖的WordPress設定頁面。

    wordpress初始化

警告:請勿在此頁面上保留WordPress安裝。如果其他使用者找到了它,他們可以在您的例項上建立一個網站並使用它來提供惡意內容。

通過建立使用者名稱和密碼來安裝WordPress或刪除您的例項。

刪除WordPress

  1. 執行以下命令以刪除您的金鑰,部署,服務和PersistentVolumeClaims:

    kubectl delete -k ./
    

相關文章