<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>

【Kubernetes】K8s筆記(十二):中級篇實戰和小結

Kubernetes 技術要點回顧

Kubernetes 是云原生時代的操作系統,它能夠管理大量節點構成的集群,讓計算資源“池化”,從而能夠自動地調度運維各種形式的應用。

使用 kubeadm 搭建集群

【Kubernetes】K8s筆記(七):中級篇 - 搭建多節點實驗環境

搭建多節點的 Kubernetes 集群是一件頗具挑戰性的工作,好在社區里及時出現了 kubeadm 這樣的工具。

kubeadm 使用容器技術封裝了 Kubernetes 組件,所以只要節點上安裝了容器運行時(cri-o containerd 等),它就可以自動從網上拉取鏡像,然后以容器的方式運行組件,非常簡單方便。

配置 Control-Plane

$ sudo kubeadm init \
	--apiserver-advertise-address=<host_ip> \
	--image-repository registry.aliyuncs.com/google_containers \
	--kubernetes-version=<version>\
	--pod-network-cidr=10.10.0.0/16

配置 Worker

$ sudo kubeadm join 192.168.165.133:6443 --token <token> \
        --discovery-token-ca-cert-hash <hash>

Deployment API 對象

【Kubernetes】K8s筆記(八):Deployment 發布無狀態的應用

Deployment 是用來管理 Pod 的一種對象,它代表了運維工作中最常見的一類在線業務,在集群中部署應用的多個實例,而且可以很容易地增加或者減少實例數量,從容應對流量壓力。

Deployment 的定義里有兩個關鍵字段:一個是 replicas,它指定了實例的數量;另一個是 selector,它的作用是使用標簽“篩選”出被 Deployment 管理的 Pod,這是一種非常靈活的關聯機制,實現了 API 對象之間的松耦合。

DaemonSet API 對象

【Kubernetes】K8s筆記(九):DaemonSet 守護進程集

DaemonSet 是另一種部署在線業務的方式,它很類似 Deployment,但會在集群里的每一個節點上運行一個 Pod 實例,類似 Linux 系統里的“守護進程”,適合日志、監控等類型的應用。

DaemonSet 能夠任意部署 Pod 的關鍵概念是“污點”(taint)和“容忍度”(toleration)。Node 會有各種“污點”,而 Pod 可以使用“容忍度”來忽略“污點”,合理使用這兩個概念就可以調整 Pod 在集群里的部署策略。

Service API 對象

【Kubernetes】K8s筆記(十):Service 解決服務發現的關鍵問題

Service 是對 Pod IP 地址的抽象,它擁有一個固定的 IP 地址,再使用 iptables 規則把流量負載均衡到后面的 Pod,節點上的 kube-proxy 組件會實時維護被代理的 Pod 狀態,保證 Service 只會轉發給健康的 Pod。Service 還基于 DNS 插件支持域名,所以客戶端就不再需要關心 Pod 的具體情況,只要通過 Service 這個穩定的中間層,就能夠訪問到 Pod 提供的服務。

Ingress / Ingress Class API 對象和 Ingress Controller 組件

【Kubernetes】K8s筆記(十一):Ingress 集群進出流量總管

Ingress 定義了基于 HTTP 協議的路由規則。

Ingress Controller 是真正的集群入口,控制集群南北向流量,應用 Ingress 規則調度、分發流量,此外還能夠扮演反向代理的角色,提供安全防護、TLS 卸載等更多功能。

Ingress Class 是用來管理 Ingress 和 Ingress Controller 的概念,方便我們分組路由規則,降低維護成本。

不過 Ingress Controller 本身也是一個 Pod,想要把服務暴露到集群外部還是要依靠 Service。Service 支持 NodePort、LoadBalancer 等方式,但 NodePort 的端口范圍有限,LoadBalancer 又依賴于云服務廠商,都不是很靈活。折中的辦法是用少量 NodePort 暴露 Ingress Controller,用 Ingress 路由到內部服務,外部再用反向代理或者 LoadBalancer 把流量引進來。

一個好消息是 Kubernetes 正在進行 Gateway API 對象的開發,現在它已經進入 Beta 階段。

Gateway API 是以 Gateway 資源(代表底層網絡網關/代理服務器)為中心的資源集合, Kubernetes 服務網絡的健壯性得益于眾多供應商實現、得到廣泛行業支持且極具表達力、可擴展和面向角色的各個接口。
Gateway API 最初被認為是知名 Ingress API 的繼任者, Gateway API 的好處包括(但不限于)對許多常用網絡協議的顯式支持 (例如 HTTP、TLS、TCP 、UDP) 以及對傳輸層安全 (TLS) 的緊密集成支持。 特別是 Gateway 資源能夠實現作為 Kubernetes API 來管理網絡網關的生命周期。

實戰架構

這次部署 WordPress,所有的相關應用都運行在 Kubernetes 集群之中,部署方式都是 Deployment。之前的 Nginx 換成了 Nginx Ingress Controller。WordPress 現在有了多個實例。MariaDB 因為要保證數據一致性暫時還只有一個實例,當然后面我們還可以使用 TiDB 這類分布式數據庫。

因為 Kubernetes 內置了服務發現機制 Service,我們再也不需要去手動查看 Pod 的 IP 地址了,只要為它們定義 Service 對象,然后使用域名就可以訪問 MariaDB、WordPress 這些服務。

網站對外提供服務的兩種方式:

  • 讓 WordPress 的 Service 對象以 NodePort 的方式直接對外暴露端口 30088,方便測試

  • 給 Nginx Ingress Controller 添加 hostNetwork 屬性,直接使用節點上的端口號,類似 Docker 的 host 網絡模式,好處是可以避開 NodePort 的端口范圍限制

1. 部署 MariaDB

首先使用一個 ConfigMap 對象定義數據庫的環境變量:

# mariadb/mariadb-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: maria-cm

data:
  DATABASE: 'db'
  USER: 'wp'
  PASSWORD: '123'
  ROOT_PASSWORD: '123'

然后我們描述一個 Deployment 來描述 MariaDB 部署后期望的狀態,這里 replicas 設置為 1,然后使用 envFrom 把配置信息以環境變量的方式注入 Pod:

# mariadb/mariadb-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: maria-dep
  name: maria-dep

spec:
  replicas: 1
  selector:
    matchLabels:
      app: maria-dep

  template:
    metadata:
      labels:
        app: maria-dep
    spec:
      containers:
      - image: mariadb:10
        name: mariadb
        ports:
        - containerPort: 3306

        envFrom:
        - prefix: 'MARIADB_'
          configMapRef:
            name: maria-cm

還需要再為 MariaDB 定義一個 Service 對象,映射端口 3306,讓其他應用不再關心 IP 地址,直接用 Service 對象的名字來訪問數據庫服務:

# mariadb/mariadb_svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: maria-dep
  name: maria-svc

spec:
  ports:
  - port: 3306
    protocol: TCP
    targetPort: 3306
  selector:
    app: maria-dep

當然,我們也可以將這三個對象放到同一個 YAML 文件中,對象之間使用 --- 隔開,這樣就可以一次性創建好:

# mariadb/mariadb-all.yaml

# mariadb ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: maria-cm

data:
  DATABASE: 'db'
  USER: 'wp'
  PASSWORD: '123'
  ROOT_PASSWORD: '123'

---
# mariadb Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: maria-dep
  name: maria-dep

spec:
  replicas: 1
  selector:
    matchLabels:
      app: maria-dep

  template:
    metadata:
      labels:
        app: maria-dep
    spec:
      containers:
      - image: mariadb:10
        name: mariadb
        ports:
        - containerPort: 3306

        envFrom:
        - prefix: 'MARIADB_'
          configMapRef:
            name: maria-cm

---
# mariadb Service
apiVersion: v1
kind: Service
metadata:
  labels:
    app: maria-dep
  name: maria-svc

spec:
  ports:
  - port: 3306
    protocol: TCP
    targetPort: 3306
  selector:
    app: maria-dep

然后創建這些對象:

$ kubectl apply -f mariadb-all.yaml 
configmap/maria-cm created
deployment.apps/maria-dep created
service/maria-svc created

最后檢查一下對象的狀態:

$ kubectl get deploy 
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
maria-dep   1/1     1            1           19m

$ kubectl get pods -o wide 
NAME                        READY   STATUS    RESTARTS      AGE     IP           NODE         NOMINATED NODE   READINESS GATES
maria-dep-658f54c96-9zrsw   1/1     Running   0             20m     10.10.1.58   worker1      <none>           <none>

$ kubectl get svc -o wide 
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        5d22h   <none>
maria-svc    ClusterIP   10.104.144.64   <none>        3306/TCP       21m     app=maria-dep

2. 部署 WordPress

因為剛才創建了 MariaDB 的 Service,所以在寫 ConfigMap 配置的時候 HOST 就不應該是 IP 地址了,而應該是 DNS 域名,也就是 Service 的名字 maria-svc

# wordpress/wp-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: wp-cm

data:
  HOST: 'maria-svc'
  USER: 'wp'
  PASSWORD: '123'
  NAME: 'db'

編寫 WordPress 的 Deployment YAML,replicas 設置 3 個,然后用 envFrom 設置環境變量:

# wordpress/wp-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wp-dep
  name: wp-dep

spec:
  replicas: 3
  selector:
    matchLabels:
      app: wp-dep

  template:
    metadata:
      labels:
        app: wp-dep
    spec:
      containers:
      - image: wordpress:5
        name: wordpress
        ports:
        - containerPort: 80

        envFrom:
        - prefix: 'WORDPRESS_DB_'
          configMapRef:
            name: wp-cm

此時仍然要為 WordPress 創建 Service 對象,這里使用了 NodePort 類型,并且手工指定了端口號 30088(必須在 30000~32767 之間):

# wordpress/wp-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wp-dep
  name: wp-svc

spec:
  ports:
  - name: http80
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30088

  selector:
    app: wp-dep
  type: NodePort

我們還是可以使用 --- 把它們合并為一個文件:

# wordpress/wp-all.yaml

# wp-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: wp-cm

data:
  HOST: 'maria-svc'
  USER: 'wp'
  PASSWORD: '123'
  NAME: 'db'

---
# wp-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wp-dep
  name: wp-dep

spec:
  replicas: 3
  selector:
    matchLabels:
      app: wp-dep

  template:
    metadata:
      labels:
        app: wp-dep
    spec:
      containers:
      - image: wordpress:5
        name: wordpress
        ports:
        - containerPort: 80

        envFrom:
        - prefix: 'WORDPRESS_DB_'
          configMapRef:
            name: wp-cm

---
# wp-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wp-dep
  name: wp-svc

spec:
  ports:
  - name: http80
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30088

  selector:
    app: wp-dep
  type: NodePort

現在創建 WordPress 相關的對象:

$ kubectl apply -f wp-all.yaml 
configmap/wp-cm created
deployment.apps/wp-dep created
service/wp-svc created

然后檢查一下創建的所有對象:

$ kubectl get deploy -o wide 
NAME        READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES        SELECTOR
maria-dep   1/1     1            1           23m     mariadb      mariadb:10    app=maria-dep
wp-dep      3/3     3            3           4m46s   wordpress    wordpress:5   app=wp-dep

$ kubectl get pods -o wide 
NAME                        READY   STATUS    RESTARTS   AGE     IP           NODE      NOMINATED NODE   READINESS GATES
maria-dep-658f54c96-9zrsw   1/1     Running   0          23m     10.10.1.58   worker1   <none>           <none>
wp-dep-78647ffc4d-kz956     1/1     Running   0          5m13s   10.10.1.61   worker1   <none>           <none>
wp-dep-78647ffc4d-mz6x9     1/1     Running   0          5m13s   10.10.1.59   worker1   <none>           <none>
wp-dep-78647ffc4d-xchdz     1/1     Running   0          5m13s   10.10.1.60   worker1   <none>           <none>

$ kubectl get svc -o wide 
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        5d22h   <none>
maria-svc    ClusterIP   10.104.144.64   <none>        3306/TCP       23m     app=maria-dep
wp-svc       NodePort    10.100.17.219   <none>        80:30088/TCP   5m27s   app=wp-dep

因為 WordPress 的 Service 對象是 NodePort 類型的,我們可以在集群的每個節點上訪問 WordPress 服務。

查看節點 IP:

$ kubectl get nodes -o wide 
NAME         STATUS   ROLES           AGE     VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
k8s-master   Ready    control-plane   5d22h   v1.25.2   172.16.63.128   <none>        Ubuntu 22.04.1 LTS   5.15.0-52-generic   containerd://1.5.9-0ubuntu3
worker1      Ready    <none>          5d22h   v1.25.2   172.16.63.129   <none>        Ubuntu 22.04.1 LTS   5.15.0-52-generic   containerd://1.5.9-0ubuntu3

根據節點 IP 訪問 30088 端口上的 WordPress:

image

3. 部署 Nginx Ingress Controller

首先定義 Ingress Class,名字就叫 wp-ink

# wp-ingress/wp-ink.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: wp-ink

spec:
  controller: nginx.org/ingress-controller

然后用 kubectl create 命令生成 Ingress 的樣板文件,指定域名是 wp.test,后端 Service 是 wp-svc:80,Ingress Class 就是剛定義的 wp-ink

$ export out="--dry-run=client -o yaml"
$ kubectl create ing wp-ing --rule="wp.test/=wp-svc:80" --class=wp-ink $out

下面是得到的 Ingress YAML,注意路徑匹配類型是 Prefix

# wp-ingress/wp-ing.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wp-ing

spec:
  ingressClassName: wp-ink
  rules:
  - host: wp.test
    http:
      paths:
      - backend:
          service:
            name: wp-svc
            port:
              number: 80
        path: /
        pathType: Prefix

編寫 Ingress Controller 對象的 YAML,它仍然需要從 Nginx 項目的示例 YAML 修改而來,要改動名字、標簽,還有參數里的 Ingress Class:

*kic for kubernetes ingress contrller

# wp-ingress/wp-kic.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wp-kic-dep
  namespace: nginx-ingress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wp-kic-dep

  template:
    metadata:
      labels:
        app: wp-kic-dep

    spec:
      serviceAccountName: nginx-ingress
      # use host network
      hostNetwork: true
      automountServiceAccountToken: true
      containers:
      - image: nginx/nginx-ingress:2.2-alpine
        imagePullPolicy: IfNotPresent
        name: nginx-ingress
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        - name: readiness-port
          containerPort: 8081
        - name: prometheus
          containerPort: 9113
        readinessProbe:
          httpGet:
            path: /nginx-ready
            port: readiness-port
          periodSeconds: 1
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"

        securityContext:
          allowPrivilegeEscalation: true
          runAsUser: 101 #nginx
          runAsNonRoot: true
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        args:
          - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
          - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
          - -ingress-class=wp-ink

這個 Ingress Controller 不使用 Service,而是給它的 Pod 加上一個特殊字段 hostNetwork,讓 Pod 能夠使用宿主機的網絡,相當于另一種形式的 NodePort。

創建上述對象:

$ kubectl apply -f wp-ink.yaml -f wp-ing.yaml -f wp-kic.yaml 
ingressclass.networking.k8s.io/wp-ink created
ingress.networking.k8s.io/wp-ing created
deployment.apps/wp-kic-dep created

檢查一下所有對象是否正常運行:

$ kubectl get deploy -n nginx-ingress -o wide 
NAME          READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS      IMAGES                           SELECTOR
wp-kic-dep    1/1     1            1           62s   nginx-ingress   nginx/nginx-ingress:2.2-alpine   app=wp-kic-dep

$ kubectl get pods -n nginx-ingress -o wide 
NAME                           READY   STATUS    RESTARTS       AGE   IP              NODE      NOMINATED NODE   READINESS GATES
wp-kic-dep-6577bf795f-2zq89    1/1     Running   0              82s   172.16.63.129   worker1   <none>           <none>

$ kubectl get ing -o wide 
NAME      CLASS     HOSTS      ADDRESS   PORTS   AGE
wp-ing    wp-ink    wp.test              80      2m24s

4. 測試

首先向 /etc/hosts 文件中添加一條記錄,IP 地址是 nginx-ingress 所在節點的 IP 地址:

172.16.63.129   wp.test

現在瀏覽器直接訪問 wp.test 即可:

image

總結

這個網站離真正實用還差得比較遠,但框架已經很完善了,可以在這個基礎上添加其他功能,比如創建證書 Secret、讓 Ingress 支持 HTTPS 等等。

另外,對于數據庫 MariaDB 來說,雖然 Deployment 在發生故障時能夠及時重啟 Pod,新 Pod 卻不會從舊 Pod 繼承數據,之前網站的數據會徹底消失,這個后果是完全不可接受的。所以后面會繼續學習持久化存儲對象 PersistentVolume,以及有狀態的 StatefulSet 等對象。

posted @ 2022-10-24 10:39  joexu01  閱讀(135)  評論(0編輯  收藏  舉報
人碰人摸人爱免费视频播放

<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>