天天看點

雲原生(6)-k8s入門必看篇1.資源2. NameSpace3. pod4. Deployment5. Service6. Ingress7. 存儲8 總結

k8s的安裝教程可以看上一篇 https://developer.aliyun.com/article/806212

1.資源

k8s中所有的對象可以稱為k8s的資源,之前安裝k8s時就已經體驗過k8s的資源了

k8s中資源的建立方式:

  1. 指令行
  2. yaml 如安裝calico時使用的yaml

2. NameSpace

命名空間,主要用來隔離資源,預設不隔離網絡

2.1 使用指令行操作名稱空間:

# 檢視名稱空間

kubectl get ns/namespace

# 建立名稱空間

kubectl create ns [名稱空間名]

# 删除名稱空間 會删除該名稱空間下的所有資源

kubectl delete ns [名稱空間名]

同樣的,可以解析下之前用過的指令

# -A是擷取所有資源,如果不加-A 會預設使用default名稱空間 也可以指定名稱空間

kubectl get pod -A

# 指定名稱空間

kubectl get pod -n [名稱空間名]

2.2 使用yaml操作名稱空間

建立如下yaml配置檔案 hello.yaml

建立時注意格式,注釋需要去掉

apiVersion: v1 #版本号

kind: Namespace #資源類型 指定為namespace

metadata: #中繼資料

 name: hello #命名空間名稱

# 建立名稱空間資源

kubectl apply -f hello.yaml

# 删除名稱空間資源

kubectl delete -f hello.yaml

k8s中使用配置檔案建立的資源都可以通過配置檔案删除

3. pod

pod是k8s中運作的最小機關,也是運作的一組容器

pod相對于k8s來說,與docker中的容器概念類似

如下圖所示,解釋pod的概念

docker是k8s運作的基礎環境,

pod是k8s的最小機關,但是一個pod中可以有多個容器在運作,不同的pod是互相隔離的

雲原生(6)-k8s入門必看篇1.資源2. NameSpace3. pod4. Deployment5. Service6. Ingress7. 存儲8 總結

3.1 pod基本操作指令

3.1.1 指令行方式操作pod

# 建立pod

kubectl run [pod名] --image=[鏡像名]

example:

kubectl run mynginx --image=nginx

# 檢視pod建立日志

kubectl describe pod [pod名]

# 删除pod 可以在後面加上-n [namespace名]

kubectl delete pod [pod名]

3.1.2 YAML方式操作pod

建立如下内容yaml pod.yaml

apiVersion: v1

kind: Pod #資源類型

metadata:

  labels:

    run: mynginx

  name: mynginx # pod名稱

spec:

  containers:

    - image: nginx #鏡像

      name: mynginx

kubectl apply -f pod.yaml

# 删除pod

kubectl delete -f pod.yaml

3.1.3 dashboard操作pod

界面化操作,略

3.1.4 pod的一些常用指令

pod的指令與docker 容器的相關指令類似

# 檢視pod運作日志

kubectl logs [-f] [pod名]

# 檢視pod詳細資訊 -owide檢視詳細資訊 包括pod的ip

kubectl get pod [-n namespace] -owide

# 進入pod

kubectl exec -it [pod名] -- /bin/bash

3.1.5 多容器pod

建立如下内容的yaml, multicontainers.yaml

kind: Pod

    run: myapp

  name: myapp

    - image: nginx

     name: nginx

    - image: tomcat:8.5.68

     name: tomcat

kubectl apply -f multicontainers.yaml

一個pod中不能啟動兩個相同的容器,端口沖突導緻啟動失敗

4. Deployment

通過Deployment使pod擁有多副本,自愈,擴縮容的能力

# 原來的建立pod

# 通過Deployment建立pod

kubectl create deployment my_deployment_nginx --image=nginx

通過deployment建立的pod,再删除(當機)後會自動重新建立一個pod,這就是k8s的自愈能力

# 删除deployment

kubectl delete deploy my_deployment_nginx

4.1 多副本

deployment可以啟動多個pod,稱之為副本

# 建立多副本 replicas副本數

kubectl create deployment my_tomcat_deployment --image=tomcat:8.5.68 --replicas=3

dashboard同樣可以操作

雲原生(6)-k8s入門必看篇1.資源2. NameSpace3. pod4. Deployment5. Service6. Ingress7. 存儲8 總結

4.2 擴縮容

通過deployment可以對pod進行擴縮容,增加/減少pod的數量

4.2.1 指令行擴縮容

# 擴縮容 指定副本數即可

kubectl scale deployment/[deployment名] --replicas=5

4.2.2 yaml擴縮容

# 使用edit指令

kubectl edit deploy [deployment名]

# 修改replicas屬性 儲存後即可

4.2.3 dashboard擴縮容

4.3 自愈&故障轉移

自愈: pod發生故障後,k8s重新開機該pod後正常,稱為自愈

故障轉移: pod所在機器可能發生故障(斷電等特殊情況),k8s在其他節點重新拉起故障節點的pod,稱為故障轉移

# 測試自愈 在某個pod所在節點 停止容器

docker stop [容器名]

# 可以看到k8s會自動重新開機該pod

# 測試故障轉移,直接将某個pod所在節點關機

# 可以看到5min後,k8s會重新開機拉起一個pod

4.4 滾動更新

滾動更新: 在修改deployment的鏡像時(更新),會先新啟一個新版本的pod,當新版本的pod啟動後,再停止老版本的pod,依次對老版本的pod進行此操作,最終達到更新鏡像的效果

# 滾動更新 鏡像名可以通過deployment的yaml中尋找,就是- image下的name屬性

kubectl set image deploy/[deployment名] [鏡像名]=[新鏡像名] --record

4.5 版本回退

一個deployment經過多次更新後,會産生多個版本,可以通過版本回退回退到某一個版本

# 檢視曆史版本  加--revision 可以看到某一個版本的詳情

kubectl rollout history deployment/[deployment名]

# 回退到某一個版本 不加--revision預設會復原到上一個版本

kubectl rollout undo deployment/[deployment名] --revision=[通過檢視曆史看到的版本号]

# 檢視復原後的deployment的yaml配置檔案

kubectl get deploy/[deployment名] -oyaml | grep [查找項]

版本回退的過程也是一次滾動更新

4.6 其他工作負載

deployment是其中一種工作負載

deployment是無狀态的,針對于微服務這種業務資料都存在與中間件中的應用

除此之外,還有其他的工作負載

  • 有狀态工作負載: StatefulSet 提供穩定的存儲,網絡等功能
  • 守護應用工作負載: DaemonSet 比如日志收集元件,每個機器運作一份
  • 定時應用工作負載: Job/CronJob 比如垃圾清理元件,定時運作

5. Service

Service:是将多個pod對外暴露成一個服務,可以實作對pod的服務發現和負載均衡

舉例:

有三個微服務pod,每個pod有自己的IP,前端調用的時候無法自動的負載,需要背景來暴露出唯一的一個ip,通過service就可以做到,而且當某一個pod挂了之後,Service就可以将之後的流量打入其他兩個pod中,實作服務發現的功能

# 暴露服務 --port為暴露端口 --target-port為目标端口即原pod的端口

kubectl expose deploy [deployment名] --port=8000 --target-port=80

# 檢視服務 可以擷取暴露服務的ip

kubectl get service

此時可以使用服務ip:服務port通路該Service

同時在叢集容器内部,可以使用 域名:port 通路

域名規則: Service名.NameSpace名.svc

這種叢集内部可以通路的方式 就是ClusterIP方式 即叢集ip方式

這個時候傳回來看之前的 k8s-dashboard的搭建,當時修改了type為 NodePort,即節點端口方式

5.1 服務發現

Service會對pod進行動态的發現,當某個pod離線後,就不會将流量繼續負載給該pod,當擴容一個pod後,Service也會自動将該pod納入負載的範圍内,根據一定的政策将流量分發至該pod

5.2 端口暴露方式

Service主要就是端口的暴露,分為兩種方式

5.2.1 ClusterIP

# ClusterIP模式也是預設的 即不加--type就是ClusterIP

kubectl expose deploy [deployment名] --port=[暴露端口] --target_port=[pod服務端口] --type=ClusterIP

以叢集IP的方式暴露端口,此時在叢集内部可以通過

  1. 叢集内部ip:port的方式通路
  2. 也可以通過域名:端口的方式通路

5.2.2 NodePort

以目前機器節點的方式暴露端口

kubectl expose deploy [deployment名] --port=[暴露端口] --target_port=[pod服務端口] --type=NodePort

# 此時查詢service

kubectl get svc

可以看到除了叢集ip port之外,又多一個端口 這就是目前伺服器的端口

此時可以通過伺服器ip+此端口即可通路(注意放行安全組)

k8s生成的NodePort node範圍為 30000- 32767之前,可以在安全組内直接對此範圍内的端口放行

6. Ingress

Ingress是k8s-Service的入口,相當于統一網關,底層是Nginx

通過Ingress将不同的請求分發至不同的Service

官網:

https://kubernetes.github.io/ingress-nginx/deploy/

6.1 安裝

k8s預設沒有安裝Ingress,需要手動安裝

# 下載下傳ingress-nginx

wget

https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml

# 修改ingress-nginx的鏡像源 改為阿裡雲

vi deploy.yaml

registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0

# 安裝

kubectl apply -f deploy.yaml

# 檢視安裝服務

kubectl get pod,svc -n ingress-nginx

# 放行svc端口

6.2 使用

安裝後,檢視服務就可以看到ingress-nginx 命名空間下的服務,可以通過此服務暴露的端口來通路

Ingress也是一個Service

注意: Ingress會暴露兩個端口

雲原生(6)-k8s入門必看篇1.資源2. NameSpace3. pod4. Deployment5. Service6. Ingress7. 存儲8 總結

80的為http請求端口

443的為https請求端口

6.2.1 測試

測試的目的是通過Ingress來通路不同的Service

架構如下:

雲原生(6)-k8s入門必看篇1.資源2. NameSpace3. pod4. Deployment5. Service6. Ingress7. 存儲8 總結

6.2.1.1 準備工作

6.2.1.1.1 建立deploy/Service

建立兩個deploy,并将其暴露成Service

建立如下yaml, test.yaml

apiVersion: apps/v1

kind: Deployment

  name: hello-server

  replicas: 2

  selector:

    matchLabels:

      app: hello-server

  template:

    metadata:

      labels:

        app: hello-server

    spec:

      containers:

      - name: hello-server

        image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server

        ports:

        - containerPort: 9000

---

    app: nginx-demo

  name: nginx-demo

      app: nginx-demo

        app: nginx-demo

      - image: nginx

        name: nginx

kind: Service

  ports:

  - port: 8000

    protocol: TCP

    targetPort: 80

    app: hello-server

    targetPort: 9000

裡面分别建立了兩個 Deployment 并暴露成Service,啟動兩個Deployment的鏡像就是簡單的hello-server和nginx

通路hello-server傳回一個hello字元串

通路nginx傳回nginx的首頁

# 建立如上資源

kubectl apply -f test.yaml

6.2.1.1.2 建立Ingress

建立如下yaml ingress.yaml,

rules配置的很類似gateway的配置

host就是請求的域名,根據域名來轉發到不同的Service

apiVersion: networking.k8s.io/v1

kind: Ingress  

  name: ingress-host-bar

  ingressClassName: nginx

  rules:

  - host: "hello.zy.com"

    http:

      paths:

      - pathType: Prefix

        path: "/" # 字首是/後的所有請求會被轉發至service

        backend:

          service:

            name: hello-server # 轉發至的service

            port:

              number: 8000 # service端口

  - host: "demo.zy.com" # 多個規則

        path: "/" 

            name: nginx-demo

              number: 8000

# 建立ing

kubectl apply -f ingress.yaml

6.2.1.2 使用域名測試

便于測試,我們就直接修改windows hosts檔案,不使用公網ip解析

将任意k8s節點ip配置至hosts檔案

[ip] hello.zy.com

[ip] demo.zy.com

浏覽器通路 hello.zy.com 轉發到 hello-server的service處理

浏覽器通路 nginx.zy.com 轉發到 nginx-demo的service處理

6.2.2 重寫路徑

上述Ingress的配置檔案中配置的是/後的所有請求會被轉發到對應的Service,我們也可以對轉發的路徑進行重寫,類似于GateWay/Nginx重寫路徑的方式

官網文檔:

https://kubernetes.github.io/ingress-nginx/examples/rewrite/

kind: Ingress

  annotations:

    nginx.ingress.kubernetes.io/rewrite-target: /$2 # 第二個參數

  name: rewrite

  namespace: default

  - host: rewrite.bar.com

      - path: /something(/|$)(.*) # 通配符

        pathType: Prefix

            name: http-svc

            port: 

              number: 80

6.2.3 流量控制

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting

參考文檔增加如下annotations參數即可

# rps不能大于1 否則傳回503 預設503 可以修改

nginx.ingress.kubernetes.io/limit-rps: "1"

6.3 總結

通過ingress來回顧一下k8s安裝初始化主節點時的指令

kubeadm init \

--apiserver-advertise-address=172.16.0.208 \

--control-plane-endpoint=cluster-endpoint \

--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \

--kubernetes-version v1.20.9 \

--service-cidr=10.96.0.0/16 \

--pod-network-cidr=192.168.0.0/16

其中最後兩個參數

service-cidr

pod-network-cidr

此時就可以明白啥意思

  • service-cidr 為service層的網絡範圍
  • pod-network-cidr 為pod的網絡範圍

而此時也可以建立起k8s的網絡模型

雲原生(6)-k8s入門必看篇1.資源2. NameSpace3. pod4. Deployment5. Service6. Ingress7. 存儲8 總結

7. 存儲

docker有将容器内的目錄挂載到主控端的能力,同樣的k8s也可以挂載,但是不能像docker一樣直接挂載到實體機的某個目錄

原因是 我們的pod/deploy存在故障轉移的能力,如果将某個pod的檔案挂載到固定的機器下,當我們的pod發生了故障轉移之後,再另外一個節點上重新啟動了一個pod時,就會發生找不到之前的資料的問題,如果我們的pod是一個存儲類的中間件 如mysql時,找不到之前的資料将是災難的

針對如上的情況,k8s将存儲抽象出來,作為一個單獨的存儲層,存儲層使用分布式的檔案存儲系統來實作,如NFS

NFS會把各個節點的檔案進行同步

通過分布式檔案存儲系統的特性,使我們的pod即時在别的節點重新開機也可以擷取到之前挂載在分布式檔案存儲系統的資料.

k8s對存儲是開放的,可以使用多種分布式檔案存儲系統.

7.1 NFS搭建

我們對k8s的三台伺服器搭建nfs

# 所有節點安裝nfs工具包

yum install -y nfs-utils

# 主節點初始化目錄

# 暴露nfs/data目錄,此目錄可以自定義

echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports

# 建立上述暴露目錄

mkdir -p /nfs/data

# 啟動

systemctl enable rpcbind --now

systemctl enable nfs-server --now

# 使nfs配置生效

exportfs -r

此時主節點已經初始化完畢,有一個/nfs/data的目錄暴露出來

# 從節點檢視主目錄 ip為主節點IP 此處可以使用區域網路ip 前提處于一個vpc下

showmount -e 172.31.0.4

# 從節點建立目錄

# 從節點目錄挂載 ip為主節點ip 目錄為上述建立目錄

mount -t nfs 172.31.0.4:/nfs/data /nfs/data

# 測試 在任意一節點新增/修改檔案,檢視另外兩個節點是否同步

echo "hello nfs server" > /nfs/data/test.txt

7.2 deployment挂載目錄

yaml配置如下

    app: nginx-pv-demo

  name: nginx-pv-demo

      app: nginx-pv-demo

        app: nginx-pv-demo

        volumeMounts: # 挂載

        - name: html # 挂載名稱

          mountPath: /usr/share/nginx/html # 容器内要挂載的目錄

      volumes: # 挂載配置

        - name: html # 對應上面配置的name

          nfs: # 此處可以改為其他fs

            server: 172.31.0.4 # nfs ip

            path: /nfs/data/nginx-pv # nfs路徑,需要先在nfs上建立出對應的路徑,否則會挂載失敗

kubectl apply -f [xx.yml]

這樣就将多個pod中的檔案挂載到nfs上,隻要nfs上的檔案修改,每個節點的檔案都會随之修改,并且容器内部的檔案也會随之修改(類似Docker).

7.3 挂載問題

上面的挂載存在兩個問題:

  1. pod删除,nfs裡的檔案不會随之删除
  2. 挂載時,無法指定某個pod挂載目錄的可使用空間

為了解決上面的問題,有兩種方案:

  1. PV&PVC

7.3.1 PV&PVC

PV(Persistent Volume): 持久卷 存儲資料

PVC(Persistent Volume Claim): 持久卷申明 說明持久卷的規格(大小)

PV和PVC都是k8s的資源類型

概述: PV就是資料存儲的地方,PVC就是描述PV大小的說明,一個pod建立的時候可以指定自己的PVC,通過PVC再綁定一個PV,這樣就達到上面pod的挂載問題

7.3.1.1 PV的使用

PV分為靜态配置設定和動态配置設定兩種

7.3.2.1 靜态配置設定

7.3.2.1.1 PV池

提前建立一個PV池,配置設定好各種規格的PV,當使用PVC綁定PV的時候會根據PVC中指定的大小來自适應(向上取大)擷取合适大小的PV.

如下yaml,建立pv池 pv.yml

kind: PersistentVolume

  name: pv01-10m #pv名字

  capacity:

    storage: 10M # pv的大小

  accessModes:

    - ReadWriteMany

  storageClassName: nfs

  nfs:

    path: /nfs/data/01 #nfs的檔案路徑

    server: 172.31.0.4 #nfs的ip

  name: pv02-1gi

    storage: 1Gi

    path: /nfs/data/02

    server: 172.31.0.4

  name: pv03-3gi

    storage: 3Gi

    path: /nfs/data/03

# 建立如上三個pv

kubectl apply -f pv.yml

# 檢視pv池

kubectl get pv

7.3.2.1.2 PVC建立

如下yaml,建立PVC pvc.yml

kind: PersistentVolumeClaim

  name: nginx-pvc # 名字

  resources:

    requests:

      storage: 200Mi # 需要的大小

  storageClassName: nfs # 與pv中的保持一緻

# 建立PVC

kubectl apply -f pvc.yml

# 此時k8s就會選擇最合适大小的pv來與PVC綁定,如上文中PVC的大小 200M 那麼就會選擇 pv02-1gi 這個PV來綁定

kubectl get pvc

7.3.2.1.3 建立pod綁定PVC

如下yaml, pod-pvc.yml

    app: nginx-deploy-pvc

  name: nginx-deploy-pvc

      app: nginx-deploy-pvc

        app: nginx-deploy-pvc

        volumeMounts:

        - name: html

          mountPath: /usr/share/nginx/html

      volumes:

          persistentVolumeClaim:

            claimName: nginx-pvc # 挂載PVC

# 建立使用PVC挂載的pod

kubectl apply -f pod-pvc.yml

7.3.2.2 動态配置設定

動态配置設定就是動态的增加PV并将其配置設定給pod使用

7.4 ConfigMap

配置集: 專為配置檔案挂載使用的資源類型

類似Docker中的-v 參數,但是将挂載的配置檔案抽象成了一種資源類型

底層儲存資料使用的是k8s的鍵值資料庫: ETCD

# 建立redis的配置檔案

echo appendonyl yes > redis.conf

# 建立配置集

kubectl create cm redis-conf --from-file=redis.conf

建立pod,cm.yml

  name: redis

  - name: redis

    image: redis

    command:

      - redis-server

      - "/redis-master/redis.conf"  #指的是redis容器内部的位置

    ports:

    - containerPort: 6379

    volumeMounts:

    - mountPath: /data

      name: data

    - mountPath: /redis-master

      name: config # 對應下面volumes中的cm配置

  volumes:

    - name: data

      emptyDir: {}

    - name: config # 配置項

      configMap:

        name: redis-conf # cm的名稱

        items:

        - key: redis.conf # 檔案名

          path: redis.conf # 挂載到redis中的檔案

7.5 Secret

類似于ConfigMap,但是是針對密鑰,令牌等東西存儲的

舉例: 建立pod拉取鏡像時可能需要私有鏡像倉庫的密鑰,此時通過Secret就可以做到一次配置,多次使用的效果

##指令格式

kubectl create secret docker-registry [secret名] \

  --docker-server=<你的鏡像倉庫伺服器> \

  --docker-username=<你的使用者名> \

  --docker-password=<你的密碼> \

  --docker-email=<你的郵箱位址>

  name: private-nginx

  - name: private-nginx

    image: zy/mynginx:v1.0

  imagePullSecrets:

  - name: zy-docker # 建立的secret名稱

8 總結

通過上面的學習,簡單的了解了k8s中的大部分資源類型及使用方式,可以通過指令行的方式來操作k8s底層的各種東西

熟悉了k8s的網絡模型,知道k8s叢集中服務流量的分發規則.

學無止境!

繼續閱讀