Kubernetes简介手册
关于这篇文章
这是一个收集了有关Kubernetes(简称K8s)命令的备忘单。我们将重点整理K8s的基本命令kubectl的用法,同时通过实际操作一个简单的K8s集群来学习。
环境
作为运行k8s的环境
-
- ローカルではminikube
- AWS EKS
有很多选择,为了简单起见,我们决定使用minikube来建立本地环境。
只要调整权限,EKS集群基本上可以以相同的方式使用。
准备好
请参考以下URL,安装 minikube:
(https://kubernetes.io/docs/tasks/tools/install-minikube/)
首先,启动minikube,并确认集群的IP。
$ minikube start
...
$ minikube ip
192.168.99.101
确认设置
让我们使用K8s的基本命令kubectl来查看信息。
查看全部设定
我认为,虽然在Minikube或EKS中这些设置是自动创建的,但如果了解其内容,当出现问题时会更容易处理,所以我会解释一下。
设定文件可以在 ~/.kube/config 中找到,但也可以通过 kubectl config view 命令查看。
从 kubectl config view 的结果中,我提取了有关 minikube 的信息。
- cluster:
certificate-authority: /Users/zawawahoge/.minikube/ca.crt
server: https://192.168.99.101:8443
name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
在结构上,有一个名为minikube的cluster,并且有一个名为minikube的context引用它。
首先,在cluster中注册集群IP和认证密钥,然后context引用它。
刚才的集群IP也被写入到配置文件中。
接下来,让我们使用 kubectl 来确认关于连接的目标集群信息的上下文。
上下文是指 Kubernetes 为了方便连接多个集群而提供的关于集群和项目连接信息的内容。
详细来说,
-
- name(コンテクストそのものの名前)
-
- cluster(どのクラスタ設定を使うか)
-
- user(どういうユーザとしてクラスタに接続するか)
-
- authinfo
- namespace(名前空間)
是由…组成的。
查看当前设置的上下文列表
可以使用kubectl config get-contexts命令。
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* minikube minikube minikube
尽管Minikube的默认值有些平淡,但像EKS集群这样的情况下名称会更加复杂。
确认默认的上下文名称
$ kubectl config current-context
minikube
上下文是关于客户端试图通过kubectl连接到集群的信息,所以即使进行了修改,也不会在远程端反映出来。如果想要连接到不同的集群或命名空间,需要创建一个新的上下文或编辑现有的上下文。
创建新的背景信息
$ kubectl config set-context my-context
Context "my-context" created.
$ kubectl config get-contexts my-context
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
my-context
一个全新的环境被建立起来了。
编辑上下文
$ kubectl config set-context my-context --namespace new-namespace --cluster minikube
Context "my-context" modified.
$ kubectl config get-contexts my-context
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
my-context minikube new-namespace
更改默认上下文
$ kubectl config use-context my-context
Switched to context "my-context".
更改默认上下文的命名空间。
在实际应用中,虽然连接的集群是相同的,但可能会有需要更改命名空间的情况。这时候,只需要改写当前上下文的命名空间就可以了。
# 変更前のコンテクストの詳細
$ kubectl config get-contexts $(kubectl config current-context)
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* my-context minikube new-namespace
$ kubectl config set-context --current --namespace new-new-namespace
Context "my-context" modified.
# 変更後のコンテクストの詳細
$ kubectl config get-contexts $(kubectl config current-context)
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* my-context minikube new-new-namespace
设定背景细节
$ kubectl config view
# デフォルトのコンテクストの設定詳細
$ kubectl config view --minify
实际运行集群并观察结果。
前座時間有点长,但现在让我们实际运行minikube的集群吧。
我们将部署一个相当简单的集群,其中有三个由nginx镜像创建的容器。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
将默认上下文设置为minikube,以便准备好访问集群。
kubectl config use-context minikube
Switched to context "minikube".
部署集群
$ kubectl apply -f nginx-deploy.yaml
查看有关集群的信息列表
在k8s中,
-
- Deployment
-
- ReplicaSet
-
- Pod
- Service
使用kubectl get命令,可以获取集群的信息。当使用all选项时,将输出上述四个选项的全部内容。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-56db997f77-6rvxq 1/1 Running 0 8m27s
pod/nginx-56db997f77-9w55k 1/1 Running 0 8m27s
pod/nginx-56db997f77-ptw9c 1/1 Running 0 8m27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 3/3 3 3 8m27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-56db997f77 3 3 3 8m27s
如果只想查看部署情况时,可以将”all”替换为”deploy”。
添加”-o wide”选项可以增加输出的信息量。
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 11m
$ kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx 3/3 3 3 11m nginx nginx app=nginx
查看詳細設定
使用-o yaml或-o json选项,可以查看更详细的信息。刚才应用的yaml文件写得非常简略,但是命令可以查看省略的默认值。
kubectl get deploy -o yaml的结果如下:
apiVersion: v1
items:
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"nginx","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2019-05-11T17:51:32Z"
generation: 1
name: nginx
namespace: default
resourceVersion: "211356"
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx
uid: 693dc4b4-7415-11e9-9b1f-0800273e0575
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 3
conditions:
- lastTransitionTime: "2019-05-11T17:54:24Z"
lastUpdateTime: "2019-05-11T17:54:24Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2019-05-11T17:51:32Z"
lastUpdateTime: "2019-05-11T17:54:24Z"
message: ReplicaSet "nginx-56db997f77" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 3
replicas: 3
updatedReplicas: 3
kind: List
metadata:
resourceVersion: ""
selfLink: ""
我得到了相当详细的信息。
查看Pod列表
如果使用“-o wide”选项,显示的信息会增加。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-56db997f77-6rvxq 1/1 Running 0 22m 172.17.0.10 minikube <none> <none>
nginx-56db997f77-9w55k 1/1 Running 0 22m 172.17.0.9 minikube <none> <none>
nginx-56db997f77-ptw9c 1/1 Running 0 22m 172.17.0.8 minikube <none> <none>
寻找Pod名称的列表
使用awk命令可以轻松提取Pod名称列表。将显示第二行及以后的第一列。
# Pod名のリストを表示
$ kubectl get pods | awk 'NR>1{print $1}'
nginx-56db997f77-6rvxq
nginx-56db997f77-9w55k
nginx-56db997f77-ptw9c
# PodのIPのリストを表示
$ kubectl get pods -o wide | awk 'NR>1{print $6}'
172.17.0.9
172.17.0.8
172.17.0.4
获取具有特定标签的 Pod 列表
当使用-l选项指定标签时,只提取具有特定标签的POD。
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-56db997f77-6rvxq 1/1 Running 2 36h
nginx-56db997f77-9w55k 1/1 Running 2 36h
nginx-56db997f77-ptw9c 1/1 Running 2 36h
访问集群内的容器
这三个Pod分别具有集群中的私有IP地址。
作为k8s的特点,同一集群中的Pod可以使用这个私有IP地址相互通信。
让我们实际验证一下。
为访问群集内部,创建临时的Pod。
我创建了一个只用于通过busybox执行wget命令的Pod,然后向IP地址为172.17.0.10的Pod发送请求,成功收到了index.html的响应。
$ kubectl run -i -t busybox --image=busybox --restart=Never
/ # wget 172.17.0.10:80
Connecting to 172.17.0.10:80 (172.17.0.10:80)
index.html 100% |****************************************************************************************| 612 0:00:00 ETA
/ # ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 scope link src 172.17.0.11
# このPodのプライベートIPは172.17.0.11
试着进入集装箱内
使用kubectl exec命令,可以实现与docker exec相同的功能,访问Pod中的容器。
$ kubectl exec -it nginx-56db997f77-6rvxq bash
root@nginx-56db997f77-6rvxq:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@nginx-56db997f77-6rvxq:/#
只要nginx日志是输出到标准输出的,我们可以使用kubectl logs命令来确认。
检查Pod的容器输出的日志
$ kubectl logs nginx-56db997f77-6rvxq
172.17.0.11 - - [11/May/2019:18:28:39 +0000] "GET / HTTP/1.1" 200 612 "-" "Wget" "-"
因为刚才发送HTTP请求的发送源busybox容器的IP地址是172.17.0.11,所以我知道日志已经正确保存了。
服务
使用负载均衡器将外部通信路由到Pod
我确认了三个nginx的Pod正常运行,但是从集群外面无法进行通信。有一种名为Load balancer的Service类型可以在外部通过指定的方式将通信路由到Pod上。
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
selector:
app: nginx
ports:
- port: 80
type: LoadBalancer
应用-f命令后,将创建一个新的Service。
我觉得你可能会担心该Service会不会正确地与Deployment和负载均衡器结合起来。
实际上,由于选择器与Deployment相匹配,所以Service能够找到对应的Deployment。
$ kubectl apply -f nginx-service.yaml
service/nginx-lb created
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
nginx-lb LoadBalancer 10.99.193.167 <pending> 80:32328/TCP 10s
由于在minikube上,此Service处于Pending状态,因此无法访问。
从0.31.0版本开始,minikube添加了一个名为minikube tunnel的功能,使用它可以实现访问。
参考资料:https://qiita.com/inajob/items/4025a1d1aa83721c453d
$ minikube tunnel
Status:
machine: minikube
pid: 45884
route: 10.96.0.0/12 -> 192.168.99.101
minikube: Running
services: [nginx-lb]
errors:
minikube: no errors
router: no errors
loadbalancer emulator: no errors
再试一次,确实显示了EXTERNAL-IP。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
nginx-lb LoadBalancer 10.109.96.98 10.109.96.98 80:32425/TCP 10m
$ curl 10.109.96.98
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...(略)
请注意,在实际的 AWS 运营中,必须使用 EKS 服务可用的负载均衡器,这样才能从外部进行访问。