整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          通過搭建MySQL掌握k8s重要概念(上):網絡與持

          通過搭建MySQL掌握k8s重要概念(上):網絡與持久卷

          一篇"通過實例快速掌握 k8s(Kubernetes)核心概念[1]"講解了 k8s 的核心概念,有了核心概念整個骨架就完整了,應付無狀態程序已經夠了,但還不夠豐滿。應用程序分成兩種,無狀態和有狀態的。一般的前段和后端程序都是無狀態的,而數據庫是有狀態的,他需要把數據存儲起來,這樣即使斷電,數據也不會丟失。要創建有狀態的程序,還需要引入另外一些 k8s 概念。它們雖然不是核心,但也很重要,共有三個,持久卷,網絡和參數配置。掌握了這些之后,基本概念就已經做到了全覆蓋,k8s 就已經入門了。我們通過搭建 MySQL 來熟悉這些 k8s 概念。容器本身是無狀態的,一旦出現問題它會被隨時銷毀,它存儲的數據也就丟失了。MySQL 需要一個能保存數據的持久層,在容器被銷毀之后仍然存在,k8s 叫它持久卷。

          創建和驗證 MySQL 鏡像:

          在 k8s 上安裝 MySQL 之前,先用 Docker 驗證一下 MySQL 鏡像:

          docker run --name test-mysql -p 3306:33060 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
          

          “root”是根(root)用戶的 password,這里是在創建 MySQL 容器時指定“root”用戶的 password?!皌est-MySQL”是容器的名字。“mysql:5.7”用的是 docker 庫里的“MySQL”5.7 版本。這次沒有用最新的 8.0 版,因為新版跟以前的客戶端不兼容,需要修改很多東西。所用的鏡像是全版的 Linux,因而文件比較大,有 400M。

          容器建好了之后,鍵入“docker logs test-mysql”,查看日志。

          ...
          2019-10-03T06:18:50.439784Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.17' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
          2019-10-03T06:18:50.446543Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060
          

          查看容器狀態。

          vagrant@ubuntu-xenial:~$ docker ps
          CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
          3b9c50420f5b mysql:latest "docker-entrypoint.s…" 11 minutes ago Up 11 minutes 3306/tcp, 33060/tcp test-mysql
          

          為了驗證 MySQL,需要在虛機上安裝 MySQL 客戶端。

          sudo apt-get -y -f install mysql-client
          

          完成之后,鍵入“docker inspect test-mysql”找到容器 IP 地址, 下面顯示"172.17.0.2"是容器 IP 地址。

          vagrant@ubuntu-xenial:~$ docker inspect test-mysql
          ...
           "Gateway": "172.17.0.1",
           "IPAddress": "172.17.0.2",
           "IPPrefixLen": 16,
           "IPv6Gateway": "",
          ...
          

          鍵入“mysql -h 172.17.0.2 -P 3306 --protocol=tcp -u root -p”登錄到 MySQL,"172.17.0.2"是 MySQL 的 IP 地址,“3306”是 MySQL 端口,是在創建鏡像時設定的對外開放的端口,“root”是用戶名,“-p”是 password 的參數選項。敲入命令后,系統要求輸入 password,輸入后,顯示已成功連接到 MySQL。

          vagrant@ubuntu-xenial:~$ mysql -h 172.17.0.2 -P 3306 --protocol=tcp -u root -p
          ...
          Welcome to the MySQL monitor. Commands end with ; or \g.
          Your MySQL connection id is 3
          Server version: 5.7.27 MySQL Community Server (GPL)
          ...
          

          在 k8s 上安裝 MySQL

          在 k8s 上安裝 MySQL 分成三個部分,創建部署文件,創建服務文件和安裝測試。

          部署(Deployment)文件

          下面是部署配置文件。在上一篇文章中已經詳細講解了文件格式,所有的 k8s 的配置文件格式都是相同的。“template”之上是部署配置,從“template”向下是 Pod 配置。從“containers”開始是 Pod 里面的容器配置。“env:”是環境變量,這里通過環境變量來設置數據庫的用戶名和口令,后面還會詳細講解。MySQL 的端口是“3306”

          apiVersion: apps/v1
          kind: Deployment # 類型是部署
          metadata:
           name: mysql-deployment # 對象的名字
          spec:
           selector:
           matchLabels:
           app: mysql #用來綁定label是“mysql”的Pod
           strategy:
           type: Recreate
           template: # 開始定義Pod
           metadata:
           labels:
           app: mysql #Pod的Label,用來標識Pod
           spec:
           containers: # 開始定義Pod里面的容器
           - image: mysql:5.7
           name: mysql-con
           imagePullPolicy: Never
           env: # 定義環境變量
           - name: MYSQL_ROOT_PASSWORD # 環境變量名
           value: root # 環境變量值
           - name: MYSQL_USER
           value: dbuser
           - name: MYSQL_PASSWORD
           value: dbuser
           args: ["--default-authentication-plugin=mysql_native_password"]
           ports:
           - containerPort: 3306 # mysql端口
           name: mysql
          

          服務(Service)文件

          下面是服務配置文件,這個與上一篇講的配置基本相同,這里就不解釋了。

          apiVersion: v1
          kind: Service
          metadata:
           name: mysql-service
           labels:
           app: mysql
          spec:
           type: NodePort
           selector:
           app: mysql
           ports:
           - protocol : TCP
           nodePort: 30306
           port: 3306
           targetPort: 3306
          

          安裝測試:

          有了配置文件后,下面就開始創建 MySQL。在創建時要按照順序,依次進行,先從最底層的對象開始創建。

          創建部署和服務:

          kubectl apply -f mysql-deployment
          kubectl apply -f mysql-service.yaml
          

          查看服務:

          vagrant@ubuntu-xenial:~$ kubectl get service
          NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
          kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h42m
          mysql-service NodePort 10.102.253.32 <none> 3306:30306/TCP 3h21m
          

          “mysql-service”的端口(PORT(S))有兩個,“3306”是 k8s 內部端口,“30306”是外部端口。由于“NodePort”已經打開了對外端口,這時就可以在虛擬機上通過“30306”端口訪問 MySQL。

          vagrant@ubuntu-xenial:~$ mysql -h localhost -P 30306 --protocol=tcp -u root -p
          Enter password:
          Welcome to the MySQL monitor. Commands end with ; or \g.
          Your MySQL connection id is 6
          Server version: 5.7.27 MySQL Community Server (GPL)
          ...
          mysql>
          

          這時本地虛機已經與 k8s 聯通了,下一步就可以在宿主機( 筆記本)上用圖形客戶端來訪問 MySQL 了。我是在 Vagrant 里設定了私有網絡,設定的虛機 IP 地址是 "192.168.50.4”,就用這個地址和 30306 端口來訪問 MySQL。

          網絡:

          這里的網絡有兩層含義,一層是 k8s 網絡,就是讓 k8s 內部服務之間可以互相訪問,并且從 k8s 集群外部可以訪問它內部的服務。另一層是宿主機(筆記本)和虛機之間的網路,就是在宿主機上可以訪問虛機。這兩層都通了之后,就可以在宿主機直接訪問 k8s 集群里面的 MySQL。

          k8s 網絡:

          k8s 的網絡也有兩層含義,一個是集群內部的,k8s 有內部 DNS,可以通過服務名進行尋址。另一個是從集群外部訪問集群內部服務,一共有四種方式,詳情請見“Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?[2]

          • LoadBalancer:Load Balancer 不是由 K8s 來管理的。k8s 通過 Load Balancer 把外部請求轉發給內部服務。這種方法要求有 Load Balancer,一般云環境里會提供,但自己的本地環境就沒有了。不過 Minikube 提供了一個程序可以模擬 Load Balancer。你只要鍵入“minikube tunnel ”,它就會模擬 Load Balancer,對請求進行轉發。只不過當你在使用“Load Balancer”時(在 Minikube 環境里),每次運行服務時產生的 IP 和端口是隨機的,不能控制,使用起來不太方便,但在正式環境里就沒有這個問題。下面是服務信息,“EXTERNAL-IP”是"pending",說明外部網絡不通。
          $ kubectl get service
          NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
          kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
          nginx-service LoadBalancer 10.104.228.212 <pending> 80:31999/TCP 45h
          

          下面是在運行“minikube tunnel ”(在另一個窗口運行)之后的服務信息,“EXTERNAL-IP”是 “10.104.228.212”。這時 Minikube 的 LoadBalancer 已經起作用了,現在就可以通過 IP 地址從外部訪問 k8s 內部的服務了,“80”是 k8s 內部端口,“31999”是 k8s 對外端口。

          $ kubectl get service
          NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
          kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
          nginx-service LoadBalancer 10.104.228.212 10.104.228.212 80:31999/TCP 45h
          

          這是一種比較好的方式,但不能控制它的 IP 地址和端口,因此我暫時沒有采用它。

          • NodePort:這種方法可以在每個 Node 上開放一個對外端口,每一個指向這個端口的請求都被轉發給一個服務。它的好處是你可以指定一個固定的端口(端口的取值范圍只能是 30000–32767),這樣我在筆記本上訪問 MySQL 時就不用更換端口了。如果你不指定,系統會隨機分配一個。它的缺點是每個端口只能有一個服務,而且端口取值受限制,因此不適合生產環境。但在 Windows 環境,由于我用 Vagrant 固定了虛機的 IP 地址,這個問題就不存在了。因此它是最好的選擇。
          • ClusterIP: 這個只能在 k8s 集群內部尋址。
          • Ingress: 這是推薦的方法,一般在生產環境中使用。Load balancer 的問題是每一個服務都要有一個 Load balancer,服務多了之后會很麻煩,這時就會用 Ingress,它的缺點是配置起來比較復雜。Minikube 自帶了一個基于 Nginx 的 Ingress 控制器,只需運行“minikube addons enable ingress”,就行了。但 Ingress 的設置較復雜,因此這里沒有用它。

          虛擬機網絡:

          這里講的是宿主機(筆記本)和虛機之間的互相訪問,主要是從宿主機訪問虛機。我用的是 Vagrant, 因此要在 Vagran 的配置文件(Vagrantfile)里進行配置。它有兩種方法:

          • 端口轉發:它可以把筆記本上特定端口的請求轉發到虛機的指定端口,還是比較方便的。只是如果事先不知道是哪個端口,或端口是變化的,就比較麻煩。Vagrant 的配置命令:“config.vm.network "forwarded_port", guest: 3306, host: 3306, auto_correct: true”
          • 私有網絡:這是一種很靈活的方式。可以給宿主機和虛機各自設定一個固定的 IP 地址,這樣可以雙向互訪。任何端口都沒有問題,唯一的缺點就是你要事先確定 IP 地址。詳情請參見“Vagrant reverse port forwarding?”[3]。Vagrant 的配置命令:“config.vm.network "private_network", ip: "192.168.50.4”

          當配置私有網絡時,需要在筆記本的 VirtualBox 上配置“Host-only Adapter”,如下圖所示。

          但這會造成在 Vagrant 啟動 Minikube 時產生如下錯誤:“VBoxManage.exe: error: Failed to create the host-only adapter”。這是 VirtualBox 的一個 Bug,你可以下載一個軟件解決,詳見這里[4]. 這個軟件已經是四年之前的了,開始還擔心是否與現在的 VirtualBox 版本兼容,結果很好用,而且它是一個單獨運行的軟件,不會與現在的軟件沖突。只要在啟動虛機之前,用管理員身份運行這個補丁就行了。另外一個問題是,我原來使用的是 5.x 版的 VirtualBox,上圖中只能選“NAT”,不能選“Host-only Adapter”,升級到 6.X 之后才能選“Host-only Adapter”。但當虛機重新啟動之后,它會自動變回“NAT”,不過私有網絡還是可用。

          創建持久卷(PersistentVolume):

          k8s 卷的概念包括卷和持久卷。

          卷(volume):

          卷是 k8s 的存儲概念,它依附于 Pod,不能單獨存在。但它不是在容器層。因此如果容器被重新啟動,卷仍然在。但如果 Pod 重新啟動,卷就丟失了。如果一個 Pod 里有多個容器,那么這些容器共享 Pod 的卷。你可以把卷看成是一個目錄,里面可以存儲各種文件。k8s 支持各種類型的卷,例如本地文件系統和各種云存儲。

          持久卷(PersistentVolume):

          是對卷的一個封裝,目的是為了更好地管理卷。它的生命周期不需要與 Pod 綁定,它可以獨立于 Pod 存在。

          持久卷申請(PersistentVolumeClaim):

          是對持久卷資源的一個申請,你可以申請特定的存儲容量的大小和訪問模式,例如讀寫模式或只讀模式。k8s 會根據持久卷申請分配適合的持久卷,如果沒有合適的,系統會自動創建一個。持久卷申請是對持久卷的一個抽象,就像編程里的接口(Interface),它可以有不同的具體實現(持久卷)。例如,阿里云和華為云支持的存儲系統不同,它生成的持久卷也不相同。持久卷是與特定的存儲實現綁定的。那你要把程序從阿里云移植到華為云,怎么保證配置文件的兼容性呢?你就用持久卷申請來做這個接口,它只規定存儲容量大小和訪問模式,而由阿里云和華為云自動生成各自云里滿足這個接口需求的持久卷. 不過,它還有一個限制條件,那就是持久卷申請和持久卷的 StorageClass 需要匹配,這使它沒有接口靈活。后面會詳細講解。

          動態持久卷:

          在這種情況下,你只需創建持久卷申請(不需要單獨創建持久卷),然后把持久卷申請與部署綁定。系統會按照持久卷申請自動創建持久卷。下面是持久卷申請配置文件。其中“storage:1Gi”,是指申請的空間大小是 1G。

          持久卷申請配置文件:

          apiVersion: v1
          kind: PersistentVolumeClaim
          metadata:
           name: mysql-pv-claim
           labels:
           app: mysql
          spec:
           accessModes:
           - ReadWriteOnce
           resources:
           requests:
           storage: 1Gi #持久卷的容量是 1 GB
          

          掛載持久卷申請的部署:

          下面是掛載了持久卷申請的部署配置文件。它通過把持久卷申請當做持久卷來使用,與 Pod 進行綁定。請閱讀文件里有關持久卷的注釋。

          apiVersion: apps/v1
          kind: Deployment
          metadata:
           name: mysql-deployment
          spec:
           selector:
           matchLabels:
           app: mysql
           strategy:
           type: Recreate
           template:
           metadata:
           labels:
           app: mysql
           spec:
           containers:
           - image: mysql:5.7
           name: mysql-con
           imagePullPolicy: Never
           env:
           - name: MYSQL_ROOT_PASSWORD
           value: root
           - name: MYSQL_USER
           value: dbuser
           - name: MYSQL_PASSWORD
           value: dbuser
           args: ["--default-authentication-plugin=mysql_native_password"]
           ports:
           - containerPort: 3306
           name: mysql
           volumeMounts: # 掛載Pod上的卷到容器
           - name: mysql-persistent-storage # Pod上卷的名字,與“volumes”名字匹配
           mountPath: /var/lib/mysql # 掛載的Pod的目錄
           volumes: # 掛載持久卷到Pod
           - name: mysql-persistent-storage # 持久卷名字, 與“volumMounts”名字匹配
           persistentVolumeClaim:
           claimName: mysql-pv-claim # 持久卷申請名字
          

          這里只指定了 Pod 的掛載目錄,并沒有指定虛擬機(宿主機)的目錄,后面會講到如何找到虛擬機的目錄(系統自動分配掛載目錄)。

          運行部署:

          鍵入“kubectl apply -f mysql-volume.yaml”創建持久卷申請,在創建它的同時,系統自動創建持久卷。

          查看持久卷申請

          vagrant@ubuntu-xenial:~/dockerimages/kubernetes/mysql$ kubectl get pvc
          NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
          mysql-pv-claim Bound pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa 1Gi RWO standard 10m
          

          查看持久卷申請詳細信息

          vagrant@ubuntu-xenial:/mnt$ kubectl describe pvc mysql-pv-claim
          Name: mysql-pv-claim
          Namespace: default
          StorageClass: standard
          Status: Bound
          Volume: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa
          Labels: app=mysql
          ...
          

          顯示持久卷:

          vagrant@ubuntu-xenial:/mnt$ kubectl get pv
          NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
          pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa 1Gi RWO Delete Bound default/mysql-pv-claim standard 24h
          

          鍵入“kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa”, 顯示持久卷詳細信息。從這里可以看出,虛擬機上的持久卷在如下位置:“Path:/tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa”。

          vagrant@ubuntu-xenial:/mnt$ kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa
          Name: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa
          Labels: <none>
          Annotations: hostPathProvisionerIdentity: 19948fdf-e67f-11e9-8fbd-026a5b40726f
           pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath
          Finalizers: [kubernetes.io/pv-protection]
          StorageClass: standard
          Status: Bound
          Claim: default/mysql-pv-claim
          Reclaim Policy: Delete
          Access Modes: RWO
          VolumeMode: Filesystem
          Capacity: 1Gi
          Node Affinity: <none>
          Message:
          Source:
           Type: HostPath (bare host directory volume)
           Path: /tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa
           HostPathType:
          Events: <none>
          

          查看 MySQL 目錄信息:

          vagrant@ubuntu-xenial:/tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa$ ls -al
          total 188488
          drwxrwxrwx 6 999 docker 4096 Oct 4 13:23 .
          drwxr-xr-x 3 root root 4096 Oct 4 12:58 ..
          -rw-r----- 1 999 docker 56 Oct 4 12:58 auto.cnf
          -rw------- 1 999 docker 1679 Oct 4 12:59 ca-key.pem
          -rw-r--r-- 1 999 docker 1107 Oct 4 12:59 ca.pem
          -rw-r--r-- 1 999 docker 1107 Oct 4 12:59 client-cert.pem
          -rw------- 1 999 docker 1679 Oct 4 12:59 client-key.pem
          -rw-r----- 1 999 docker 668 Oct 4 13:21 ib_buffer_pool
          -rw-r----- 1 999 docker 79691776 Oct 4 13:23 ibdata1
          -rw-r----- 1 999 docker 50331648 Oct 4 13:23 ib_logfile0
          -rw-r----- 1 999 docker 50331648 Oct 4 12:58 ib_logfile1
          -rw-r----- 1 999 docker 12582912 Oct 4 13:24 ibtmp1
          drwxr-x--- 2 999 docker 4096 Oct 4 12:58 mysql
          drwxr-x--- 2 999 docker 4096 Oct 4 12:58 performance_schema
          -rw------- 1 999 docker 1679 Oct 4 12:59 private_key.pem
          -rw-r--r-- 1 999 docker 451 Oct 4 12:59 public_key.pem
          -rw-r--r-- 1 999 docker 1107 Oct 4 12:59 server-cert.pem
          -rw------- 1 999 docker 1675 Oct 4 12:59 server-key.pem
          drwxr-x--- 2 999 docker 4096 Oct 4 13:18 service_config
          drwxr-x--- 2 999 docker 12288 Oct 4 12:58 sys
          

          持久卷的回收模式:

          當持久卷和持久卷申請被刪除后,它有三種回收模式。

          • 保持(Retain):當持久卷申請被刪除后,持久卷仍在。你可以手動回收持久卷里的數據。
          • ** 刪除(Delete)**:持久卷申請和持久卷都被刪除,底層存儲的數據也會被刪除。當使用動態持久卷時,缺省的模式是 Delete。當然,你可以在持久卷被創建之后修改它的回收模式。
          • ** 回收(Recycle)**:這種方式已經不推薦使用了,建議用 Retain 代替。

          靜態持久卷:

          動態持久卷的一個問題是它的缺省回收模式是“刪除”,這樣當虛機重新啟動后,持久卷會被刪除。當你重新運行部署時,k8s 會創建一個新的 MySQL,這樣原來 MySQL 里的新建信息就會丟失,這是我們不愿意看到的。雖然你可以手動修改回收方式為“保持”,但還是要手動回收原來持久卷里的數據。一個解決辦法是把持久卷建在宿主機上,這樣即使虛機出了問題被重新啟動,MySQL 里的新建信息依然不會丟失。如果是在云上,就會有專門的的存儲層,如果是本地,大致有三種方式:

          • **Local:**把存儲從宿主機掛載到 k8s 集群上. 詳情請參見:"Volumes[5]".
          • HostPath:也是把存儲從宿主機掛載到 k8s 集群上,但它有許多限制,例如只支持單節點(Node),而且只支持“ReadWriteOnce”模式。詳情請參見:"hostPath as volume in kubernetes[6]".
          • NFS:網絡文件系統,這種是最靈活的,但需要安裝 NFS 服務器。詳情請參見:"Kubernetes Volumes Guide[7]".

          我選擇了比較簡單的“Local”方式。在這種方式下,必須單獨創建持久卷,不能 只創建持久卷申請而讓系統自動創建持久卷。

          下面是使用“Local”方式的配置文件,它把持久卷和持久卷申請寫在了一個文件里。當用“Local”方式時,需要設置“nodeAffinity”部分,其中“values:- minikube” 的“Minikube”是 k8s 集群 Node 的名字,“Minikube”只支持一個 Node,既是“Master Node”,又是“Worker Node”。

          持久卷和申請的配置文件:

          apiVersion: v1
          kind: PersistentVolume
          metadata:
           name: mysql-pv
          spec:
           capacity:
           storage: 1Gi
           volumeMode: Filesystem
           accessModes:
           - ReadWriteOnce
           storageClassName: standard #持久卷存儲類型,它需要與持久卷申請的類型相匹配
           local:
           path: /home/vagrant/database/mysql #宿主機的目錄
           nodeAffinity:
           required:
           nodeSelectorTerms:
           - matchExpressions:
           - key: kubernetes.io/hostname
           operator: In
           values:
           - minikube # Node的名字
          ---
          apiVersion: v1
          kind: PersistentVolumeClaim
          metadata:
           name: mysql-pv-claim
           labels:
           app: mysql
          spec:
           accessModes:
           - ReadWriteOnce
           # storageClassName: # 這里的存儲類型注釋掉了
           resources:
           requests:
           storage: 1Gi #1 GB
          

          如果不知道 Node 名字,可用如下命令查看:

          vagrant@ubuntu-xenial:/$ kubectl get node
          NAME STATUS ROLES AGE VERSION
          minikube Ready master 6d3h v1.15.2
          

          改用靜態持久卷之后,只有持久卷配置文件發生了變化,部署和服務的配置文件沒有變。重新運行持久卷和部署,成功之后,即使重啟虛擬機,MySQL 里面的新建內容也沒有丟失。

          注意這里 storageClassName 的用法。k8s 規定持久卷和持久卷申請的 storageClassName 必須匹配,這時才會把持久卷分配給持久卷申請。我們這里的持久卷申請沒有指定 storageClassName,這時系統會使用缺省的 storageClass。

          查看是否安裝了缺省的 storageClass

          vagrant@ubuntu-xenial:/$ kubectl get sc
          NAME PROVISIONER AGE
          standard (default) k8s.io/minikube-hostpath 6d3h
          vagrant@ubuntu-xenial:/$
          

          查看缺省的 storageClass 詳細信息

          vagrant@ubuntu-xenial:/$ kubectl describe sc
          Name: standard
          IsDefaultClass: Yes
          Annotations: storageclass.kubernetes.io/is-default-class=true
          Provisioner: k8s.io/minikube-hostpath
          Parameters: <none>
          AllowVolumeExpansion: <unset>
          MountOptions: <none>
          ReclaimPolicy: Delete
          VolumeBindingMode: Immediate
          Events: <none>
          

          從這里可以看出,Minikube 安裝了缺省的 storageClass,它的名字是“standard”。上面的持久卷申請里沒有指定 storageClass,因此系統使用缺省的 storageClass 與之匹配,而上面的持久卷的 storageClassName 是“standard”,正好能配上。詳情請見“Dynamic Provisioning and Storage Classes in Kubernetes[8]

          踩過的坑:

          1. 使用 Hyper-V 還是 VirtualBoxHyper-V 和 VirtualBox 是不兼容的,只能選一個(當然你可以在這兩者之間切換,但太麻煩了)。我在 Windows 上裝了 VirtualBox,運行正常。進入 Vagrant 之后,安裝了“ubuntu”版的 Linux。這時,當你啟動 Minikube 時,可以鍵入“minikube start --vm-driver=virtualbox”,但系統顯示“This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory”。我按照網上的建議去修改 BIOS 的“VT-X/AMD-v”,但我的 BIOS 就沒有這個選項。其他的方法也都試過了,沒有一個成功的。但因為已經裝了 VirtualBox,就不能用 Hyper-V 了。就只能用另外一個方法,使用命令“minikube start --vm-driver=none”。幸好這個方法工作得很好。

          當用“minikube start --vm-driver=virtualbox”時,你是先建了虛擬機,再在虛擬機上運行 Minikube。當用“minikube start --vm-driver=none”時,是直接在宿主機上運行 Minikube。但由于我的 Windows 版本不能直接支持 k8s,我已經在 Windows 上裝了 Linux 虛機,并用 Vagrant 進行管理。如果用“minikube start --vm-driver=virtualbox”,就是在 Linux 虛機上又裝了一個虛機?,F在用“minikube start --vm-driver=none”,表面上看是在宿主機上運行,實際上已經運行在 Windows 的 Linux 虛機上了。

          1. 登錄 k8s 集群當用“minikube start --vm-driver=none”啟動 Minikube 時,不能用“minikube ssh”登錄 k8s 集群,因為這時已經沒有虛機了,是直接安裝在宿主機上,因此不需要“minikube ssh”。但你可以登錄到 Pod 上,可用如下命令:

          " kubectl exec -ti mysql-deployment-56c9cf5857-fffth -- /bin/bash"。其中“mysql-deployment-56c9cf5857-fffth”是 Pod 名字。

          1. 創建重名 PV 或 PVC當原來的 PV 或 PVC 還在,而你又創建了一個新的 PV, 并與原來的重名,則會得到如下錯誤:

          The persistentvolumeclaim "mysql-pv-claim" is invalid: spec: forbidden: is immutable after creation except resources.requests for bound claims 這時,你需要將原來的 PV 或 PVC 刪掉,再重新創建新的。

          喜歡本文的朋友,歡迎關注“Go語言中文網”:

          參考資料

          [1]通過實例快速掌握k8s(Kubernetes)核心概念: https://blog.csdn.net/weixin_38748858/article/details/102132544

          [2]Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?: https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

          [3]“Vagrant reverse port forwarding?”: https://stackoverflow.com/a/17012410

          [4]詳見這里: https://www.virtualbox.org/attachment/ticket/14040/VBox-Win10-fix-14040.exe

          [5]Volumes: https://kubernetes.io/docs/concepts/storage/volumes/#local

          [6]hostPath as volume in kubernetes: https://stackoverflow.com/questions/50001403/hostpath-as-volume-in-kubernetes

          [7]Kubernetes Volumes Guide: https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-volumes-example-nfs-persistent-volume.html

          [8]Dynamic Provisioning and Storage Classes in Kubernetes: https://kubernetes.io/blog/2017/03/dynamic-provisioning-and-storage-classes-kubernetes/

          本文作者: 倚天碼農

          原文鏈接:https://segmentfault.com/a/1190000020669205

          者:SimpleSmile_5177

          來源:https://www.cnblogs.com/Simple-Object/p/10272326.html

          前言

          大家都知道,jvm在啟動的時候,會執行默認的一些參數。一般情況下,這些設置的默認參數應對一些平常的項目也夠用了。但是如果項目特別大了,需要增加一下堆內存的大小、或者是系統老是莫明的掛掉,想查看下gc日志來排查一下錯誤的原因,都需要咱們手動設置這些參數。

          各個參數介紹

          1.verbose:gc

          表示,啟動jvm的時候,輸出jvm里面的gc信息。格式如下:

          [Full GC 178K->99K(1984K), 0.0253877 secs]
          

          解讀 :Full GC 就表示執行了一次Full GC的操作,178K 和99K 就表示執行GC前內存容量和執行GC后的內存容量。1984K就表示內存總容量。后面那個是執行本次GC所消耗的時間,單位是秒。

          2.-XX:+printGC

          這個打印的GC信息跟上個一樣,就不做介紹了。

          3.-XX:+PrintGCDetails

          打印GC的詳細信息。格式如下:


          解讀:new generation 就是堆內存里面的新生代。total的意思就是一共的,所以后面跟的就是新生代一共的內存大小。used也就是使用了多少內存大小。0x開頭的那三個分別代表的是 底邊界,當前邊界,高邊界。也就是新生代這片內存的起始點,當前使用到的地方和最大的內存地點。

          eden space 這個通常被翻譯成伊甸園區,是在新生代里面的,一些創建的對象都會先被放進這里。后面那個12288K就表示伊甸園區一共的內存大小,91% used,很明顯,表示已經使用了百分之多少。后面的那個0x跟上一行的解釋一樣。

          from space 和to space 是幸存者的兩個區。也是屬于新生代的。他兩個區的大小必須是一樣的。因為新生代的GC采用的是復制算法,每次只會用到一個幸存區,當一個幸存區滿了的時候,把還是活的對象復制到另個幸存區,上個直接清空。這樣做就不會產生內存碎片了。

          tenured generation 就表示老年代。

          compacting perm 表示永久代。由于這兩個的格式跟前面我介紹的那個幾乎一樣,我就不必介紹了。

          4.-XX:+PrintGCTimeStamps

          打印GC發生的時間戳。格式如下:

          289.556: [GC [PSYoungGen: 314113K->15937K(300928K)] 405513K->107901K(407680K), 0.0178568 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
          
          293.271: [GC [PSYoungGen: 300865K->6577K(310720K)] 392829K->108873K(417472K), 0.0176464 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
          

          解讀:289.556表示從jvm啟動到發生垃圾回收所經歷的的時間。GC表示這是新生代GC(Minor GC)。PSYoungGen表示新生代使用的是多線程垃圾回收器Parallel Scavenge。314113K->15937K(300928K)]這個跟上面那個GC格式一樣,只不過,這個是表示的是新生代,幸存者區。后面那個是整個堆的大小,GC前和GC后的情況。Times這個顯而易見,代表GC的所消耗的時間,用戶垃圾回收的時間和系統消耗的時間和最終真實的消耗時間。

          5.-X:loggc:log/gc.log

          這個就表示,指定輸出gc.log的文件位置。(我這里寫的log/gc.log就表示在當前log的目錄里,把GC日志寫到叫gc.log的文件里。)

          6.-XX:+PrintHeapAtGC

          表示每次GC后,都打印堆的信息。(這個打印的基本格式跟上面第二條的基本類似,我也就不比多說了。)

          7.-XX:+TraceClassLoading

          監控類的加載。格式如下:

          使用這個參數就能很清楚的看到那些類被加載的情況了。

          8.-XX:+PrintClassHistogram

          跟蹤參數。這個按下Ctrl+Break后,就會打印一下信息:

          –分別顯示:序號、實例數量、總大小、類型。

          這里面那個類型,B和C的其實就是byte和char類型。

          9.-Xmx -Xms

          這個就表示設置堆內存的最大值和最小值。這個設置了最大值和最小值后,jvm啟動后,并不會直接讓堆內存就擴大到指定的最大數值。而是會先開辟指定的最小堆內存,如果經過數次GC后,還不能,滿足程序的運行,才會逐漸的擴容堆的大小,但也不是直接擴大到最大內存。

          10.-Xmn

          設置新生代的內存大小。

          11.-XX:NewRatio

          新生代和老年代的比例。比如:1:4,就是新生代占五分之一。

          12.-XX:SurvivorRatio

          設置兩個Survivor區和eden區的比例。比如:2:8 ,就是一個Survivor區占十分之一。

          13.-XX:+HeapDumpOnOutMemoryError

          發生OOM時,導出堆的信息到文件。

          14.-XX:+HeapDumpPath

          表示,導出堆信息的文件路徑。

          15.-XX:OnOutOfMemoryError

          當系統產生OOM時,執行一個指定的腳本,這個腳本可以是任意功能的。比如生成當前線程的dump文件,或者是發送郵件和重啟系統。

          16.-XX:PermSize -XX:MaxPermSize

          設置永久區的內存大小和最大值。永久區內存用光也會導致OOM的發生。

          17.-Xss

          設置棧的大小。棧都是每個線程獨有一個,所有一般都是幾百k的大小。

          buntu信息如下。

          root@hanyw:~# 
          root@hanyw:~# lsb_release -a
          No LSB modules are available.
          Distributor ID:	Ubuntu
          Description:	Ubuntu 22.04.1 LTS
          Release:	22.04
          Codename:	jammy
          root@hanyw:~# 
          root@hanyw:~# 
          root@hanyw:~# uname -r
          5.15.0-53-generic
          

          GCC幫助手冊的第19小節,第12288~13288行,如下。


          主站蜘蛛池模板: 无码人妻精品一区二区蜜桃| 亚洲AV午夜福利精品一区二区 | 国产免费一区二区三区在线观看| 成人精品视频一区二区三区不卡 | 中文字幕人妻无码一区二区三区| 国产精品伦一区二区三级视频| 亚洲一区中文字幕在线电影网 | 国产精品乱码一区二区三| 色一情一乱一伦一区二区三欧美| 国产成人一区二区三区高清| 丝袜无码一区二区三区| 精品国产一区AV天美传媒| 视频一区在线播放| 中文字幕精品一区影音先锋| 日本一道一区二区免费看| 久久亚洲国产精品一区二区| 人妻少妇精品视频三区二区一区 | 精品人无码一区二区三区 | 成人在线视频一区| 中文字幕一区二区三区久久网站| 国产凸凹视频一区二区| 台湾无码一区二区| 日韩毛片一区视频免费| 亚洲午夜在线一区| 国产午夜毛片一区二区三区| 99久久精品午夜一区二区| 相泽亚洲一区中文字幕| 日韩一区二区a片免费观看| 国产波霸爆乳一区二区| 国产日韩精品一区二区三区 | 在线播放精品一区二区啪视频| 亚洲av片一区二区三区| 亚洲熟妇AV一区二区三区宅男| A国产一区二区免费入口| 丰满爆乳无码一区二区三区| 国产亚洲一区二区精品| 精品一区二区三区在线视频观看| 国产精品视频一区二区三区| 三上悠亚一区二区观看| 深夜福利一区二区| 精品久久久久久无码中文字幕一区 |