Kubernetes概述
首先
这是一个关于Kubernetes的初学者总结和我的笔记。请注意,本文章依据技术书籍《Docker/Kubernetes 实践容器开发入门》的内容。
Kubernetes 是什么
Kubernetes是由Google主导开发的容器编排系统,旨在自动化容器的操作。它是一个集成化的系统,可以实现和管理容器编排,并提供相应的API和CLI工具供操作使用。
Kubernetes概念
在Kubernetes中运行的应用程序通过与各种资源协同工作来运行。Kubernetes的资源就像是构成应用程序部署配置的组件,有如下几种类型。
Kubernetes集群和节点
Kubernetes 集群是指管理 Kubernetes 的各种资源的集合体。Node 是已注册在 Kubernetes 集群中的 Docker 主机,用于在 Kubernetes 上部署容器。Kubernetes 集群由主节点和节点组成,如下所示。
在Master Node上部署的组件的角色如下所示。
命名空间
Kubernetes可以创建嵌套在集群中的虚拟集群,这就是Namespace的概念。构建集群时会预先准备default、docker、kube-public和kube-system这些Namespace。每个Namespace都可以设置操作权限,从而实现更为健壮和细致的权限控制。
播放器
Pod的概述
Pod是容器的集合单元,至少包含一个容器。Pod被配置在任何一个Node上,可以将同一个Pod配置在多个Node上,也可以将多个Pod配置在一个Node上。
创建Pod
使用yaml文件(也称为清单文件)来定义创建Pod所需的内容。在这个示例中,我们将定义一个由具有代理功能的Nginx和一个名为echo的应用程序组成的Pod。(假设镜像已经创建完成)
apiVersion: v1
kind: Pod # リソースの種類の指定
metadate:
name: echo # リソース名
spec: # kind属性の値次第でspec以下のスキーマが変わる
containers: # コンテナ郡の指定
- name: nginx # コンテナ名
image: example/nginx:latest # イメージ保存先
env: # 環境変数の指定
- name: BACKEND_HOST
value: localhost:8080
ports: # EXPOSEするポートの指定
- containerPort: 80
- name: echo
image: example/echo:latest
ports:
- containerPort: 8080
要将在这个文件中定义的Pod应用到Kubernetes集群中,请执行以下命令。
$ kubectl apply -f echo.yaml
pod "echo" created
你还可以使用相同的命令来添加之后要介绍的资源。
使用Pod
检查Pod的状态
通过执行以下命令,您可以获取到Pod的状态列表。如果STATUS为Running,这表示Pod内的所有容器都已处于运行状态。READY的分母表示Pod定义的容器数,分子表示已经处于运行状态的容器数。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
echo 2/2 Running 0 11m
在容器内执行命令
您可以使用以下命令在容器内执行命令。
# kubectl exec -it Pod名 コマンド -c コンテナ名
$ kubectl exec -it echo sh -c nginx
#
容器的标准输出显示
# kubectl logs -f Pod名 -c コンテナ名
$ kubectl logs -f echo -c echo
删除Pod
# kubectl delete pod Pod名
$ kubectl delete pod echo
# kubectl delete -f マニフェストファイル名
$ kubectl delete -f echo.yaml
Pod and the address of the Pod’s internal container.
每个Pod都分配了一个独特的虚拟IP地址。被分配给Pod的虚拟IP地址将与Pod内的所有容器共享。
副本集 jí)
ReplicaSet 是用于生成和管理具有相同规格的 Pod 的资源。以下是一个描述 ReplicaSet 的清单文件 echo-replicaset.yaml 的示例。
apiVersion: apps/v1
kind: ReplicaSet # リソースの種類の指定
metadate:
name: echo # リソース名
labels:
app: echo
spec: # kind属性の値次第でspec以下のスキーマが変わる
replicas: 3 # Pod数
selector:
matchLabels:
app: echo
template:
metadate:
labels:
app: echo
spec:
containers: # コンテナ郡の指定
- name: nginx # コンテナ名
image: example/nginx:latest # イメージ保存先
env: # 環境変数の指定
- name: BACKEND_HOST
value: localhost:8080
ports: # EXPOSEするポートの指定
- containerPort: 80
- name: echo
image: example/echo:latest
ports:
- containerPort: 8080
操作ReplicaSet以减少Pod数量时,减少的Pod将被删除。无法恢复已删除的Pod。因此,适合使用具有无状态特性的Pod,如Web应用程序。
部署
在 ReplicaSet 之上有一个资源称为 Deployment。Deployment 是应用程序部署的基本单元。它是为了管理和操作 ReplicaSet 而提供的资源。以下是描述 Deployment 的清单文件 echo-deployment.yaml 的示例。
apiVersion: apps/v1
kind: Deployment # リソースの種類の指定
metadate:
name: echo # リソース名
labels:
app: echo
spec: # kind属性の値次第でspec以下のスキーマが変わる
replicas: 3 # Pod数
selector:
matchLabels:
app: echo
template:
metadate:
labels:
app: echo
spec:
containers: # コンテナ郡の指定
- name: nginx # コンテナ名
image: example/nginx:latest # イメージ保存先
env: # 環境変数の指定
- name: BACKEND_HOST
value: localhost:8080
ports: # EXPOSEするポートの指定
- containerPort: 80
- name: echo
image: example/echo:latest
ports:
- containerPort: 8080
Deployment的定义与ReplicaSet并没有太大的差异。不同之处在于Deployment使得对ReplicaSet的版本管理成为可能。可以使用以下命令来确认Deployment的修订版本。
$ kubectl rollout history deployment echo
deployments "echo"
REVISION CHANGE-CASE
1 kubectl apply --filename=echo-deployment.yaml --record=true
服务 (fú wù)
Service是Kubernetes集群中为一组Pod(主要是ReplicaSet)提供路径和服务发现功能的资源。以下是一个示例,描述了两个ReplicaSet的清单文件echo-ReplicaSet-with-label.yaml。
apiVersion: apps/v1
kind: ReplicaSet # リソースの種類の指定
metadate:
name: echo # リソース名
labels:
app: echo
release: spring # ラベル
spec: # kind属性の値次第でspec以下のスキーマが変わる
replicas: 1 # Pod数
selector:
matchLabels:
app: echo
release: spring
template:
metadate:
labels:
app: echo
release: spring
spec:
containers: # コンテナ郡の指定
- name: nginx # コンテナ名
image: example/nginx:latest # イメージ保存先
env: # 環境変数の指定
- name: BACKEND_HOST
value: localhost:8080
ports: # EXPOSEするポートの指定
- containerPort: 80
- name: echo
image: example/echo:latest
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: ReplicaSet # リソースの種類の指定
metadate:
name: echo # リソース名
labels:
app: echo
release: summer # ラベル
spec: # kind属性の値次第でspec以下のスキーマが変わる
replicas: 2 # Pod数
selector:
matchLabels:
app: echo
release: summer
template:
metadate:
labels:
app: echo
release: summer
spec:
containers: # コンテナ郡の指定
- name: nginx # コンテナ名
image: example/nginx:latest # イメージ保存先
env: # 環境変数の指定
- name: BACKEND_HOST
value: localhost:8080
ports: # EXPOSEするポートの指定
- containerPort: 80
- name: echo
image: example/echo:latest
ports:
- containerPort: 8080
创建以下的清单文件来定义一个只能访问具有release=summer的Pod的Service。
apiVersion: v1
kind: Service
metadate:
name: echo
spec:
selector:
app: echo
release: summer
ports:
- name: http
port: 80
这个图表代表了Service与具有标签的Pod之间的关系。
挤入
可通过在Kubernetes集群外使用NodePort方式将Service公开到Kubernetes集群之外,但该方法仅能处理L4层级,无法进行L7层级的控制,例如基于路径切换转发到目标Service的控制。为了解决这个问题,我们引入了Ingress资源。Ingress可以实现将Service公开到Kubernetes集群外部,并同时支持基于路径的高级HTTP路由。我们可以考虑以下示例Service。
apiService: v1
kind: Service
metadata:
name: echo
spec:
selector:
app: echo
ports:
- name: http
port: 80
可以通过以下方式定义Ingress,将此Service公开到Kubernetes集群的外部。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echo
spec:
rules:
- host: example.local
http:
paths:
- path: /
backend:
serviceName: echo
servicePort: 80
持久卷 和 持久卷索取
在Kubernetes中,为了保证存储,提供了PersistentVolume和PersistentVolumeClaim这两个资源。这些资源用于创建与集群所提供的平台n相对应的持久卷。PersistentVolume代表存储的实体(在GCP中是GCEPersistentDisk),而PersistentVolumeClaim可以动态地分配所需的存储容量给PersistentVolume。下面是PersistentVolumeClaim清单文件的示例图像。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-example
spec:
accessModes: # ストレージへのマウントポリシー
- ReadWriteOnce
storageClassName: ssd # StorageClassリソースの名前
resources:
requests:
storage: 4Gi
存储类
StorageClass是一种可以定义由PersistentVolume提供的存储类型的资源。下面是一个类似于StorageClass清单文件的示例图像。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ssd
annotation:
storageclass.kubernetes.io/is-default-class: "false"
labels:
kubernetes.io/cluster-service: "true"
provisioner: kubernetes.io/gce-pd # GCPの永続ストレージであるGCEPersistentDiskに対応したVolumePlugin
parameters:
type: pd-ssd
有状态集
Deployment是根据定义的Pod规范创建Pod的资源,适用于部署唯一标识的Pod或无需持久化数据的stateless应用。相比之下,StatefulSet是用于管理持久化数据的stateful应用的资源,例如数据存储。Deployment会为Pod分配随机的标识符,而StatefulSet会按顺序分配唯一的标识符(例如pod-0,pod-1,pod-2)来创建Pod。配置文件定义与ReplicaSet几乎相同。
工作
Job 是用来管理创建一个或多个 Pod,直到指定数量的 Pod 正常完成的资源。即使 Job 下的所有 Pod 都正常结束,Pod 也不会被删除而是会被保留,因此可以在结束后分析 Pod 的日志和执行结果。因此,Job 适用于大规模计算和批处理型应用程序,而不适用于 Web 应用程序等常驻型应用程序。Job 的清单文件示例如下:
apiVersion: batch/v1
kind: Job
metadata:
name: pingpong
labels:
app: pingpong
spec:
parallelism: 3 # 同時に実行するPod数
template:
metadata:
labels:
app: pingpong
spec:
containers:
- name: pingpong
image: example/alpine:bash
command: ["/bin/sh"]
args:
- "-c"
- |
echo ['date'] ping!
sleep 10
echo ['date'] pong!
restartPolicy: Never # Pod終了時の再実行の設定
当确认Pod的状态时,已经完成的Pod将显示为”STATUS=Completed”。
计划任务
使用CronJob资源可以进行定期调度并周期性地执行Pod,而Job只能执行一次。下面是CronJob配置文件的样例。
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: pingpong
spec:
schedule: "*/1 * * * *" # Jobのスケジュール(cron記法)
jobTemplate:
spec:
template:
metadata:
labels:
app: pingpong
spec:
containers:
- name: pingpong
image: example/alpine:bash
command: ["/bin/sh"]
args:
- "-c"
- |
echo ['date'] ping!
sleep 10
echo ['date'] pong!
restartPolicy: OnFailure # Pod終了時の再実行の設定
秘密
在Kubernetes中,定义密钥资源后,可以以Base64编码的形式处理机密信息字符串。下面是Secret清单文件的示例图像。
apiVersion: v1
kind: Secret
matadata:
name: example-secret
type: Opaque
data:
.htpasswd: Base64エンコードした機密情報の文字列
在查看Secret资源时,您可以从仪表盘上以解码Base64的文件形式来确认其内容。
(集群)角色和(集群)角色绑定
Kubernetes中的RBAC机制。
RBAC中的权限控制由两个要素构成:角色定义了在Kubernetes API上可以执行的操作,而身份验证用户、组、ServiceAccount和角色之间的关系是另一个要素。这两个要素的关系可以用下面的图表示出来。
为了实现对RBAC的权限控制,Kubernetes提供了以下类型的资源。
清单文件
ClusterRole和ClusterRoleBinding的清单文件应按照以下方式编写。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pod-reader-binding
subjects: # Roleを紐付ける対象の認証ユーザー
- kind: ServiceAccount
name: user
namespace: default
roleRef: # Role
kind: ClusterRole
name: pod-reader
apiGroup: rbac.authorization.k8s.io