k8s nginx

pod部署

  1. 編寫nginx-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-storage
      mountPath: /var/log/nginx #容器內部nginx的日志
    - name: nginx-conf
      mountPath: /usr/share/nginx/html #容器內部nginx的html位置
  volumes:
  - name: nginx-storage
    hostPath:
      path: /data/logs/nginx #將宿主機的日志目錄掛載到容器中的日志目錄
  - name: nginx-conf
    hostPath:
      path: /data/nginx #將宿主機的html目錄掛載到容器中的日志目錄
  1. 執行kubectl apply -f nginx-pod.yml創建成功pod
  2. 通過kubectl get pod nginx -o wide查看pod啟動情況
[root@master k8s]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP           NODE   NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          5m17s   10.0.3.164   cdh2   <none>           <none>
  1. 通過執行kubectl exec -it nginx sh可以進入到容器內部,然后執行curl http://127.0.0.1可以查看內容
  2. 由于此刻Pod的端口還未對外暴露,因此無法在外部訪問,可以采取以下方法:
  • hostNetwork
  • hostPort
  • NodePort
  • LoadBalancer
  • Ingress

hostNetwork

這是一種直接定義Pod網絡的方式。
如果在Pod中使用hostNotwork:true配置的話,在這種pod中運行的應用程序可以直接看到pod啟動的主機的網絡接口。在主機的所有網絡接口上都可以訪問到該應用程序。以下是使用主機網絡的pod的示例定義:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  hostNetwork: true
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-storage
      mountPath: /var/log/nginx
    - name: nginx-conf
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-storage
    hostPath:
      path: /data/logs/nginx
  - name: nginx-conf
    hostPath:
      path: /data/nginx

這樣就可以訪問宿主機的80端口就可以訪問nginx的頁面了,但是這種方式的弊端就是由于k8s集群中節點很多,無法知道這個nginx的pod部署到哪個節點。
因此一般情況下除非您知道需要某個特定應用占用特定宿主機上的特定端口時才使用hostNetwork: true的方式。

hostPort

hostPort是直接將容器的端口與所調度的節點上的端口路由,這樣用戶就可以通過宿主機的IP加上來訪問Pod了

apiVersion: v1
kind: Pod
metadata:
  name: nginx-host-port
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
      hostPort: 7878
    volumeMounts:
    - name: nginx-storage
      mountPath: /var/log/nginx
    - name: nginx-conf
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-storage
    hostPath:
      path: /data/logs/nginx
  - name: nginx-conf
    hostPath:
      path: /data/nginx

這樣就可以訪問宿主機的7878端口就可以訪問nginx的頁面了,這樣做有個缺點,因為Pod重新調度的時候該Pod被調度到的宿主機可能會變動,這樣就變化了。問題通hostNetwork一樣。
用戶必須自己維護一個Pod與所在宿主機的對應關系。

NodePort

NodePort在kubenretes里是一個廣泛應用的服務暴露方式。Kubernetes中的service默認情況下都是使用的ClusterIP這種類型,這樣的service會產生一個ClusterIP,這個IP只能在集群內部訪問,要想讓外部能夠直接訪問service,需要將service type修改為 nodePort。

#聲明一個pod,然后定義一個Service去訪問pod,通過 selector來選擇標簽,這里記住,選擇的是pod中定義的標簽名,這樣定義一個Service可以負載均衡到一個標簽下的多個pod。
------------------------
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort #Service聲明為NodePort這樣將Service的端口映射到宿主機的一個端口
  ports:
    - port: 80  #Service的端口
      targetPort: 80 #Pod容器的端口
      nodePort: 30000 #宿主機的端口
  selector:
    app: nginx-node-1  #選擇 標簽為nginx-node-1的POD作為后端服務

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-node
  labels:
    app: nginx-node-1
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-storage
      mountPath: /var/log/nginx
    - name: nginx-conf
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-storage
    hostPath:
      path: /data/logs/nginx
  - name: nginx-conf
    hostPath:
      path: /data/nginx

集群外就可以使用kubernetes任意一個節點的IP加上30000端口訪問該服務了。kube-proxy會自動將流量以round-robin的方式轉發給該service的每一個pod。
這種服務暴露方式,無法讓你指定自己想要的應用常用端口,不過可以在集群上再部署一個反向代理作為流量入口。

LoadBalancer

LoadBalancer 只能在service上定義。這是公有云提供的負載均衡器,如AWS、Azure、CloudStack、GCE等。

kind: Service
apiVersion: v1
metadata:
  name: influxdb
spec:
  type: LoadBalancer
  ports:
    - port: 80
  selector:
    app: nginx-node-1
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-node
  labels:
    app: nginx-node-1
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-storage
      mountPath: /var/log/nginx
    - name: nginx-conf
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-storage
    hostPath:
      path: /data/logs/nginx
  - name: nginx-conf
    hostPath:
      path: /data/nginx

查看服務

NAME            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes      ClusterIP      192.168.0.1      <none>        443/TCP        22d     <none>
nginx-service   LoadBalancer   192.168.180.49   <pending>     80:31981/TCP   2m23s   app=nginx-node-1
使用EXTERNAL-IP來訪問,這是一個VIP,是云供應商提供的負載均衡器IP

由于只能在公有云上建立,因此此方法無法在本機進行測試演示

Ingress

Ingress是自kubernetes1.1版本后引入的資源類型。必須要部署 Ingress controller 才能創建Ingress資源,Ingress controller是以一種插件的形式提供。Ingress controller 是部署在Kubernetes之上的Docker容器。它的Docker鏡像包含一個像nginx或HAProxy的負載均衡器和一個控制器守護進程。控制器守護程序從Kubernetes接收所需的Ingress配置。它會生成一個nginx或HAProxy配置文件,并重新啟動負載平衡器進程以使更改生效。換句話說,Ingress controller是由Kubernetes管理的負載均衡器。
Kubernetes Ingress提供了負載平衡器的典型特性:HTTP路由,粘性會話,SSL終止,SSL直通,TCP和UDP負載平衡等。目前并不是所有的Ingress controller都實現了這些功能,需要查看具體的Ingress controller文檔。
ingress.yml
ingress一定要配合service使用,這樣可以使service無需使用NodeType模式,將端口部署到節點

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
spec:
  rules:
    #定義域名
    - host: test.ingress.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 80

nginx-pod.yml
這里無需將type設置為nodeType,直接去掉,無需對外訪問

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx-node-1

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-node
  labels:
    app: nginx-node-1
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-storage
      mountPath: /var/log/nginx
    - name: nginx-conf
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-storage
    hostPath:
      path: /data/logs/nginx
  - name: nginx-conf
    hostPath:
      path: /data/nginx

總結

總的來說Ingress是一個非常靈活和越來越得到廠商支持的服務暴露方式,包括Nginx、HAProxy、Traefik,還有各種Service Mesh,而其它服務暴露方式可以更適用于服務調試、特殊應用的部署。

Deployment

采用pod部署,無法進行很好的擴容操作,主流的都是是用deployment來部署,然后再結合上面的Ingress來進行負載均衡接入service

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deployment-pod
  template:
    metadata:
      labels:
        app: nginx-deployment-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-storage
          mountPath: /var/log/nginx
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-storage
        hostPath:
          path: /data/logs/nginx
      - name: nginx-html
        hostPath:
          path: /data/nginx
 
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deploy-service
spec:
  ports:
    - port: 81
      targetPort: 80
  selector:
    app: nginx-deployment-pod

執行kubectl apply -f nginx-deploy-pod.yml,查看運行情況

[root@master k8s]# kubectl get deployments -o wide
NAME               READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES        SELECTOR
nginx-deployment   2/2     2            2           69m   nginx        nginx:1.7.9   app=nginx-deployment-pod

[root@master k8s]# kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE    IP           NODE   NOMINATED NODE   READINESS GATES
nginx-deployment-78dbd4c9f4-9kw84   1/1     Running   0          11m    10.10.1.31   cdh3   <none>           <none>
nginx-deployment-78dbd4c9f4-pngnn   1/1     Running   0          11m    10.10.2.25   cdh2   <none>           <none>

Deployment + LoadBalancer模式的Service

如果要把ingress部署在公有云,那用這種方式比較合適。用Deployment部署ingress-controller,創建一個type為LoadBalancer的service關聯這組pod。大部分公有云,都會為LoadBalancer的service自動創建一個負載均衡器,通常還綁定了公網地址。只要把域名解析指向該地址,就實現了集群服務的對外暴露。

Deployment+NodePort模式的Service

同樣用deployment模式部署ingress-controller,并創建對應的Service,但是Service的type為NodePort。這樣,ingress就會暴露在集群節點ip的特定端口上。由于nodeport暴露的端口是隨機端口,一般會在前面再搭建一套負載均衡器來轉發請求。該方式一般用于宿主機是相對固定的環境ip地址不變的場景。
NodePort方式暴露ingress雖然簡單方便,但是NodePort多了一層NAT,在請求量級很大時可能對性能會有一定影響。

DaemonSet+HostNetwork+nodeSelector

用DaemonSet結合nodeselector來部署ingress-controller到特定的node上,然后使用HostNetwork直接把該pod與宿主機node的網絡打通,直接使用宿主機的80/433端口就能訪問服務。這時,ingress-controller所在的node機器就很類似傳統架構的邊緣節點,比如機房入口的nginx服務器。該方式整個請求鏈路最簡單,性能相對NodePort模式更好。缺點是由于直接利用宿主機節點的網絡和端口,一個node只能部署一個ingress-controller pod。比較適合大并發的生產環境使用。

更新deployment

  1. 升級nginx版本號,將版本號升級到1.16.1
[root@master k8s]# kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
deployment.apps/nginx-deployment image updated
deployment.apps/nginx-deployment image updated
更新后會一個個pod替換重啟
  1. 執行完命令后,要查看更新狀況
kubectl rollout status deployment/nginx-deployment

[root@master k8s]# kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out(全部更新完畢)
又或者會提示,即還有1個未更新
Waiting for rollout to finish: 1 out of 2 new replicas have been updated...

回滾

有可能更新版本出錯,這個時候可能需要回滾
1.執行回滾語句

kubectl rollout undo deployment.v1.apps/nginx-deployment

2.查看回滾狀況,同上述查看更新狀況命令一致

自動伸縮

1.指定擴容個數

[root@master k8s]# kubectl scale deployment.v1.apps/nginx-deployment --replicas=3
deployment.apps/nginx-deployment scaled
查看pod已生效
[root@master k8s]# kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE    IP           NODE   NOMINATED NODE   READINESS GATES
nginx-deployment-7fd7589cf4-h4jlz   1/1     Running   0          19s    10.10.2.29   cdh2   <none>           <none>
nginx-deployment-7fd7589cf4-hd967   1/1     Running   0          95s    10.10.2.28   cdh2   <none>           <none>
nginx-deployment-7fd7589cf4-vnvlg   1/1     Running   0          93s    10.10.1.34   cdh3   <none>           <none>

2.動態擴容個數
假設集群中啟用了水平Pod自動縮放,則可以為Deployment設置一個自動縮放器,并根據現有Pod的CPU利用率選擇要運行的最小和最大Pod數。
使用動態擴容需要為k8s創建metric-server,且為容器配置資源

kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deployment-pod
  template:
    metadata:
      labels:
        app: nginx-deployment-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        resources:
          limits: #限制最高資源
            cpu: "500m"
          requests: #最低保障資源
            cpu: "200m"
        volumeMounts:
        - name: nginx-storage
          mountPath: /var/log/nginx
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-storage
        hostPath:
          path: /data/logs/nginx
      - name: nginx-html
        hostPath:
          path: /data/nginx
 
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deploy-service
spec:
  ports:
    - port: 81
      targetPort: 80
  selector:
    app: nginx-deployment-pod
kubectl autoscale deployment.v1.apps/nginx-deployment --min=1 --max=3 --cpu-percent=50
我們可以通過運行以下命令檢查自動定標器的當前狀態:
[root@master k8s]# kubectl get hpa
NAME               REFERENCE                     TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
nginx-deployment   Deployment/nginx-deployment   <unknown>/50%   1         3         3          3m13s

K8S的資源描述:
在K8s的資源:
 CPU:
  我們知道2核2線程的CPU,可被系統識別為4個邏輯CPU,在K8s中對CPU的分配限制是對邏輯CPU做分片限制的。
  也就是說分配給容器一個CPU,實際是分配一個邏輯CPU。
  而且1個邏輯CPU還可被單獨劃分子單位,即 1個邏輯CPU,還可被劃分為1000個millicore(毫核), 簡單說就是1個邏輯CPU,繼續邏輯分割為1000個豪核心。
  豪核:可簡單理解為將CPU的時間片做邏輯分割,每一段時間片就是一個豪核心。
  所以:500m 就是500豪核心,即0.5個邏輯CPU.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 今天感恩節哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會,身份的轉變要...
    迷月閃星情閱讀 10,606評論 0 11
  • 彩排完,天已黑
    劉凱書法閱讀 4,273評論 1 3
  • 表情是什么,我認為表情就是表現出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,914評論 2 7