Skip to content

快速入门

前言

以下命令以kubernetes v2.3.8 为例

dashboard 版本: v2.5.1+0.g520013042

实践出真知,每个版本的kubernetes 改动都比较大。坑也比较多

文档仅供参考,具体以官网为主 kubernetes

下面我们简单介绍下 k8s中一些常用的命令和概念。

一、nameSpace

1. 简介

nameSpace,中文名称:命名空间。 你可以认为namespaces是你kubernetes集群中的虚拟化集群。在一个Kubernetes集群中可以拥有多个命名空间,它们在逻辑上彼此隔离。 可以为你提供组织,安全甚至性能方面的帮助!

Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是属于某一个namespace的(默认是default),而node, persistentVolumes等则不属于任何namespace。

大多数的Kubernetes中的集群默认会有一个叫default的namespace。实际上,应该是4个:

  • default:用户创建的pod默认在此命名空间。
  • kube-system:kubernetes系统组件使用。
  • kube-node-lease: kubernetes集群节点租约状态,v1.13加入
  • kube-public:公共资源使用,不需要认证也可访问。但实际上现在并不常用。

​ 这个默认(default)的namespace并没什么特别,但你不能删除它。这很适合刚刚开始使用kubernetes和一些小的产品系统。但不建议应用于大型生产系统。因为,这种复杂系统中,团队会非常容易意外地或者无意识地重写或者中断其他服务service。相反,请创建多个命名空间来把你的service(服务)分割成更容易管理的块。

作用:多租户情况下,实现资源隔离 属于逻辑隔离 属于管理边界 不属于网络边界 可以针对每个namespace做资源配额

2. 常用命令

查看 nameSpace

# 查看所有namespace
kubectl get namespace
# 简写
kubectl get ns

NAME                   STATUS   AGE
default                Active   22h
kube-node-lease        Active   22h
kube-public            Active   22h
kube-system            Active   22h
kubernetes-dashboard   Active   20h

# 查询所有pod的命名空间资源
kubectl get pod --all-namespaces
# 简写
kubectl get pod -A

NAMESPACE              NAME                                         READY   STATUS    RESTARTS   AGE
kube-system            calico-kube-controllers-7bc6547ffb-2bnbh     1/1     Running   0          21h
kube-system            calico-node-9cjvj                            1/1     Running   0          4h11m
kube-system            calico-node-q789c                            1/1     Running   0          3h36m
kube-system            calico-node-rnhcv                            1/1     Running   0          21h
kube-system            coredns-6d8c4cb4d-5bjmr                      1/1     Running   0          22h
kube-system            coredns-6d8c4cb4d-7w72l                      1/1     Running   0          22h
kube-system            etcd-k8s-master01                            1/1     Running   0          22h
kube-system            kube-apiserver-k8s-master01                  1/1     Running   0          22h
kube-system            kube-controller-manager-k8s-master01         1/1     Running   0          22h
kube-system            kube-proxy-4hsmj                             1/1     Running   0          3h36m
kube-system            kube-proxy-56nrq                             1/1     Running   0          4h11m
kube-system            kube-proxy-rcsfg                             1/1     Running   0          22h
kube-system            kube-scheduler-k8s-master01                  1/1     Running   0          22h
kubernetes-dashboard   dashboard-metrics-scraper-799d786dbf-j85zw   1/1     Running   0          5h53m
kubernetes-dashboard   kubernetes-dashboard-fb8648fd9-qcrzk         1/1     Running   0          5h53m

创建 nameSpace

shell
# 创建nameSpace
kubectl create namespace curyu
# 简写
kubectl create ns curyu

$ namespace/curyu created

删除 nameSpace

shell
# 删除nameSpace
kubectl delete namespace curyu
# 简写
kubectl delete ns curyu

$ namespace "curyu" deleted

二、pod 与 deployment

1. 简介

pod 网络只在 k8s 内部可以访问,外部无法访问。如果需要外部访问我们需要借入 service来实现。

pod是非永久性资源

Pod是kubernetes集群能够调度的最小单元。Pod是容器的封装 。

在Kubernetes集群中,Pod是所有业务类型的基础,也是K8S管理的最小单位级,它是一个或多个容器的组合。这些容器共享存储、网络和命名空间,以及如何运行的规范。在Pod中,所有容器都被统一安排和调度,并运行在共享的上下文中。对于具体应用而言,Pod是它们的逻辑主机,Pod包含业务相关的多个应用容器。

pod的特点:

  • 网络

每一个Pod都会被指派一个唯一的Ip地址,在Pod中的每一个容器共享网络命名空间,包括Ip地址和网络端口。在同一个Pod中的容器可以和localhost进行互相通信。当Pod中的容器需要与Pod外的实体进行通信时,则需要通过端口等共享的网络资源。

  • 存储

Pod能够被指定共享存储卷的集合,在Pod中所有的容器能够访问共享存储卷,允许这些容器共享数据。存储卷也允许在一个Pod持久化数据,以防止其中的容器需要被重启。

pod的工作方式

K8s一般不直接创建Pod。 而是通过控制器和模版配置来管理和调度。

  • Pod模版

工作负载资源(Deployment、StatefulSet、DaemonSet、Cornjob)的控制器通常使用 Pod 模板(Pod Template)来创建 Pod 并管理。

apiVersion: batch/v1
kind: Job
metadata:
  name: hello
spec:
  template:
    # ================== 这里是 Pod 模版  ==================
    spec:
      containers:
      - name: hello
        image: busybox
        command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
      restartPolicy: OnFailure
    # ================== 以上为 Pod 模版 ==================
  • Pod重启

在Pod中的容器可能会由于异常等原因导致其终止退出,Kubernetes提供了重启策略以重启容器。重启策略对同一个Pod的所有容器起作用,容器的重启由Node上的kubelet执行。Pod支持三种重启策略,在配置文件中通过restartPolicy字段设置重启策略:

  1. Always:只要退出就会重启。
  2. OnFailure:只有在失败退出(exit code不等于0)时,才会重启。
  3. Never:只要退出,就不再重启 注意,这里的重启是指在Pod的宿主Node上进行本地重启,而不是调度到其它Node上。
  • 资源限制

Kubernetes通过cgroups限制容器的CPU和内存等计算资源,包括requests(请求,调度器保证调度到资源充足的Node上)和limits(上限)等。

我们要知道的是: pod是k8s中的最小单元,一个pod中有可能包含多个docker,他们共享网络(ip),共享存储空间。每个pod的ip都是独立的。

一般情况下,我们并不直接创建 Pod,而是通过 Deployment 来创建 Pod由 Deployment 来负责创建、更新、维护其所管理的所有 Pods

一旦我们通过 Deployment 创建 Pod,会有一个 Deployment 控制器不断监控所有 Pod 的状态。例如,如果 Pod 运行的机器宕机了,那么 Deployment 控制器会在另一台机器上重新启动一个 Pod。

2. 常用命令

注意,不同版本的k8s 命令是由一定区别的。 比如 1.7 和 2.3 版本的deployment 命令就有一些区别。我们这里都是以2.3.8版本为例

kubernetes 1.8 开始 kubectl run 命令在运行pod的同时不会再创建 deployment。

版本变更后的办法还是用kubectl apply + yaml 文件

查看 pod

shell
# 查看 `default` namespace 下的pods
kubectl get pods
# 如果没有找到资源则展示
$ No resources found in default namespace.

# 查看 `kube-system` namespace 下的pods
kubectl get pods -n kube-system

NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-7bc6547ffb-2bnbh   1/1     Running   0          21h
calico-node-9cjvj                          1/1     Running   0          4h39m
calico-node-q789c                          1/1     Running   0          4h3m
calico-node-rnhcv                          1/1     Running   0          21h
coredns-6d8c4cb4d-5bjmr                    1/1     Running   0          23h
coredns-6d8c4cb4d-7w72l                    1/1     Running   0          23h
etcd-k8s-master01                          1/1     Running   0          23h
kube-apiserver-k8s-master01                1/1     Running   0          23h
kube-controller-manager-k8s-master01       1/1     Running   0          23h
kube-proxy-4hsmj                           1/1     Running   0          4h3m
kube-proxy-56nrq                           1/1     Running   0          4h39m
kube-proxy-rcsfg                           1/1     Running   0          23h
kube-scheduler-k8s-master01                1/1     Running   0          23h

# 查看所有 namespace 下的 pods
kubectl get pod --all-namespaces
# 简写
kubectl get pod -A

NAMESPACE              NAME                                         READY   STATUS    RESTARTS   AGE
kube-system            calico-kube-controllers-7bc6547ffb-2bnbh     1/1     Running   0          21h
kube-system            calico-node-9cjvj                            1/1     Running   0          4h40m
kube-system            calico-node-q789c                            1/1     Running   0          4h4m
kube-system            calico-node-rnhcv                            1/1     Running   0          21h
kube-system            coredns-6d8c4cb4d-5bjmr                      1/1     Running   0          23h
kube-system            coredns-6d8c4cb4d-7w72l                      1/1     Running   0          23h
kube-system            etcd-k8s-master01                            1/1     Running   0          23h
kube-system            kube-apiserver-k8s-master01                  1/1     Running   0          23h
kube-system            kube-controller-manager-k8s-master01         1/1     Running   0          23h
kube-system            kube-proxy-4hsmj                             1/1     Running   0          4h4m
kube-system            kube-proxy-56nrq                             1/1     Running   0          4h40m
kube-system            kube-proxy-rcsfg                             1/1     Running   0          23h
kube-system            kube-scheduler-k8s-master01                  1/1     Running   0          23h
kubernetes-dashboard   dashboard-metrics-scraper-799d786dbf-j85zw   1/1     Running   0          6h21m
kubernetes-dashboard   kubernetes-dashboard-fb8648fd9-qcrzk         1/1     Running   0          6h21m

创建 pod

shell
vim pod-test.yaml
#--------------------------------------
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
  labels:
    app: pod-test
spec:
  containers:
    - name: pod-container
      image: nginx
      imagePullPolicy: IfNotPresent
  restartPolicy: Always
#--------------------------------------
kubectl apply -f pod-test.yaml

修改 pod

shell
# 无论是pod、deployment、service 或是其他资源对象,都可以通过 `kubectl edit 资源类型 资源名称` 命令来进行修改。
kubectl edit pod pod-test
# 执行后会进入类似vim的页面(操作也和vim相似),我们移动光标到要修改的位置进行修改即可,修改完毕后 :wq保存,并且kubernetes会根据修改后的配置进行`自动升级、更新、启动`

删除 pod

shell
# 同样的,删除命令也和修改命令类似,可以对kubernetes资源进行操作。
# 语法:`kubectl delete 资源类型 资源名称`
# 通过pods `NAME` 删除 pod
kubectl delete deploy tomcat-test
$ pod "tomcat-test" deleted

# 除了通过`NAME` 删除,我门也可以通过 yaml 来删除,通常如果一个资源配置文件配置了多个kind,我们使用yaml的方式删除会删除的比较全。
kubectl delete -f pod-test.yaml

创建 deployment

pod 的创建 node 是随机的,因此我们在创建pod 时要确保 所有 node 的 docker image 里 都有同样的基础环境'tomcat'

我们可以通过 kubectl get pods -o wide命令得知 pod 的创建 node 及 访问ip

以下所有示例我们都使用默认的 nameSpace,即default,如果要指定nameSpace 请在命令中加入-n your nameSpace

通常我们不会直接操作pod,而是通过deployment 去管控 pod。

shell
# 为了方便整理,我们把 所有与的yaml文件都放到 master 节点的 /opt/yaml/路径下

mkdir /opt/yaml # 如果存在则忽略
cd /opt/yaml/
vim deployment_nginx.yaml
#--------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  selector:                                    #定义标签选择器
    matchLabels:                                #定义匹配的标签,必须要设置
      app: nginx                                 #匹配的目标标签
  replicas: 3                                  #开启Pod的数量
  template:                                    #定义模板,必须定义,模板是起到描述要创建的pod的作用
    metadata:                                   #定义模板元数据
      labels:                                   #定义模板label,Deployment.spec.template.metadata.labels
        app : nginx                              #定义标签,必须等于 matchLabels 定义的标签
    spec:
      containers:
        - image: nginx    #docker 镜像名,我们使用的是官方的nginx
          name: nginx                                 #镜像名称
          ports:
            - containerPort: 80                         #定义容器使用的端口
#--------------------------------------

# 而后我们创建deployment 并启动pod
kubectl apply -f /opt/yaml/deployment_nginx.yaml

$ deployment.apps/nginx-app created

# 查看 deployment
kubectl get deployment

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
my-tomcat9-test3   1/1     1            1           110m
nginx-app          0/3     3            0           14s

# 查看 deployment wide
kubectl get deployment -o wide

NAME               READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES   SELECTOR
my-tomcat9-test3   1/1     1            1           111m   tomcat       tomcat   app=my-tomcat9-test3
nginx-app          3/3     3            3           45s    nginx        nginx    app=nginx

# 查看pod wide
kubectl get pods -o wide

NAME                               READY   STATUS    RESTARTS   AGE    IP               NODE          NOMINATED NODE   READINESS GATES
my-tomcat9-test                    1/1     Running   0          123m   10.244.211.201   k8s-slave03   <none>           <none>
my-tomcat9-test3-f9d57988f-xhxhg   1/1     Running   0          111m   10.244.211.202   k8s-slave03   <none>           <none>
nginx-app-74d589986c-fkwx5         1/1     Running   0          63s    10.244.211.203   k8s-slave03   <none>           <none>
nginx-app-74d589986c-k67b2         1/1     Running   0          63s    10.244.220.197   k8s-slave02   <none>           <none>
nginx-app-74d589986c-mzpq9         1/1     Running   0          63s    10.244.220.196   k8s-slave02   <none>           <none>
tomcat-test2                       1/1     Running   0          23h    10.244.211.194   k8s-slave03   <none>           <none>

# 我们随便找一条进行测试,我们以`nginx-app-74d589986c-mzpq9`为例
# 查看 pod 节点 logs
kubectl logs nginx-app-74d589986c-mzpq9
#--------------------------------------
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/06/30 07:27:00 [notice] 1#1: using the "epoll" event method
2022/06/30 07:27:00 [notice] 1#1: nginx/1.21.5
2022/06/30 07:27:00 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2022/06/30 07:27:00 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64
2022/06/30 07:27:00 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2022/06/30 07:27:00 [notice] 1#1: start worker processes
2022/06/30 07:27:00 [notice] 1#1: start worker process 31
#--------------------------------------

# 测试访问nginx
curl 10.244.220.196:80
#--------------------------------------
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@localhost yaml]# curl 10.244.220.196:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#--------------------------------------

# 查看nginx 日志
kubectl logs nginx-app-74d589986c-mzpq9
#--------------------------------------
...
10.244.32.128 - - [30/Jun/2022:07:28:07 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.32.128 - - [30/Jun/2022:07:28:54 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.32.128 - - [30/Jun/2022:07:28:55 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
...
#--------------------------------------

# 我们还可以使用`describe` 命令来查看详细的描述信息
kubectl describe deploy nginx
#--------------------------------------
Name:                   nginx-app
Namespace:              default
CreationTimestamp:      Thu, 30 Jun 2022 15:26:44 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-app-74d589986c (3/3 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  14m   deployment-controller  Scaled up replica set nginx-app-74d589986c to 3
#--------------------------------------

#有时候我们需要在pod 中执行命令
kubectl exec -it nginx-app-74d589986c-mzpq9 bash
#--------------------------------------
root@nginx-app-74d589986c-mzpq9:/#
root@nginx-app-74d589986c-mzpq9:/# ls -l
total 12
drwxr-xr-x.   2 root root 4096 Dec 20  2021 bin
drwxr-xr-x.   2 root root    6 Dec 11  2021 boot
drwxr-xr-x.   5 root root  360 Jun 30 07:27 dev
drwxr-xr-x.   1 root root   41 Dec 29 19:28 docker-entrypoint.d
-rwxrwxr-x.   1 root root 1202 Dec 29 19:28 docker-entrypoint.sh
drwxr-xr-x.   1 root root   19 Jun 30 07:27 etc
drwxr-xr-x.   2 root root    6 Dec 11  2021 home
drwxr-xr-x.   1 root root   45 Dec 20  2021 lib
drwxr-xr-x.   2 root root   34 Dec 20  2021 lib64
drwxr-xr-x.   2 root root    6 Dec 20  2021 media
drwxr-xr-x.   2 root root    6 Dec 20  2021 mnt
drwxr-xr-x.   2 root root    6 Dec 20  2021 opt
dr-xr-xr-x. 148 root root    0 Jun 30 07:27 proc
drwx------.   1 root root   27 Jun 30 07:48 root
drwxr-xr-x.   1 root root   38 Jun 30 07:27 run
drwxr-xr-x.   2 root root 4096 Dec 20  2021 sbin
drwxr-xr-x.   2 root root    6 Dec 20  2021 srv
dr-xr-xr-x.  13 root root    0 Jun 29 01:09 sys
drwxrwxrwt.   1 root root    6 Dec 29 19:28 tmp
drwxr-xr-x.   1 root root   66 Dec 20  2021 usr
drwxr-xr-x.   1 root root   19 Dec 20  2021 var
#--------------------------------------

# 使用`ctrl + d` 退出pod 终端

删除 deployment

shell
# 通过pods `NAME` 删除 pod
kubectl delete deploy tomcat-test
$ pod "tomcat-test" deleted

# 除了通过`NAME` 删除,我门也可以通过 yaml 来删除
kubectl delete -f deployment_nginx.yaml

扩容缩容 pod

这里要注意的是:我在使用dashboard 进行 扩容、缩容操作时操作失败

pod扩容缩容

dashboard 提示操作的命令:

shell
kubectl scale -n default replicaset nginx-app-74d589986c --replicas=10

将此命令复制到 命令行中执行后,发现也失败。

现象是: 执行后确实进行了数量的缩减,但是由于异常马上又回滚了。

对比两条命令,我们发现 dashboard在缩容时 使用的 deployment 名称是nginx-app-74d589986c 而非 nginx-app

原因:dashboard为非官方提供的组件,有可能是bug 或 兼容性问题,因为k8s 每个版本的更新改动比较大。 这里我们做到心中有数就行了。

shell
# dashboard [错误]
kubectl scale -n default replicaset nginx-app-74d589986c --replicas=10
# cmd [正确]
kubectl scale deployment nginx-app --replicas=10
shell
# 我们可以通过命令去调整 pod 的数量
# 语法:  kubectl scale deployment `你的doployment名称` --replicas=`数量`
kubectl scale deployment nginx-app --replicas=10

# 查看deployment信息
kubectl get deployment -o wide

NAME        READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES   SELECTOR
nginx-app   10/20   20           10          68m   nginx        nginx    app=nginx

# 查看pods信息

NAME                         READY   STATUS    RESTARTS   AGE
my-tomcat9-test              1/1     Running   0          3h12m
nginx-app-74d589986c-4tvmd   1/1     Running   0          7m41s
nginx-app-74d589986c-8gjlj   1/1     Running   0          7m41s
nginx-app-74d589986c-bdf66   1/1     Running   0          7m41s
nginx-app-74d589986c-c4bhm   1/1     Running   0          7m41s
nginx-app-74d589986c-cq69z   1/1     Running   0          80s
nginx-app-74d589986c-d6rjk   1/1     Running   0          80s
nginx-app-74d589986c-f4g9v   1/1     Running   0          80s
nginx-app-74d589986c-gfmsd   1/1     Running   0          7m41s
nginx-app-74d589986c-gtqkd   1/1     Running   0          80s
nginx-app-74d589986c-kdq6r   1/1     Running   0          7m41s
nginx-app-74d589986c-l9m44   1/1     Running   0          80s
nginx-app-74d589986c-nffkb   1/1     Running   0          5m40s
nginx-app-74d589986c-p4mbl   1/1     Running   0          22m
nginx-app-74d589986c-p9mss   1/1     Running   0          80s
nginx-app-74d589986c-slszp   1/1     Running   0          7m41s
nginx-app-74d589986c-vb8zg   1/1     Running   0          7m41s
nginx-app-74d589986c-vgpgh   1/1     Running   0          80s
nginx-app-74d589986c-vtbzh   1/1     Running   0          80s
nginx-app-74d589986c-xszpf   1/1     Running   0          80s
nginx-app-74d589986c-xtc49   1/1     Running   0          80s
tomcat-test2                 1/1     Running   0          24h

滚动更新

滚动更新我们在后面的部分再讲解。详见 5. kubernetes 资源控制器

三、service

1. 简介

kubernetes service 有以下几个作用:

  • 提供固定的 IP。由于 Pod 可以随时启停,Pod IP 可能随时都会变化,例如上面 nginx pod 重启之后 IP 可能不再是 10.244.32.128。Service 为 Pods 提供的固定 IP,其他服务可以通过 Service IP 找到提供服务的 Pods。
  • 提供负载均衡。Service 由多个 Pods 组成,kubernetes 对组成 Service 的 Pods 提供的负载均衡方案,例如随机访问、基于 Client IP 的 session affinity。
  • 服务发现。集群中其他服务可以通过 Service 名字访问后端服务(DNS),也可以通过环境变量访问。

2. 常用命令

创建 service

shell
# 为了方便整理,我们把 所有与的yaml文件都放到 master 节点的 /opt/yaml/路径下
mkdir /opt/yaml # 如果存在则忽略
cd /opt/yaml/
vim service_nginx.yaml
#--------------------------------------
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-service # service 名称
  labels:
    app: nginx-app
spec:
  selector:                 # 选择器,将service 和 pod 相关联
    app: nginx          # 对应pod 的name(deployment name)
  ports:
  - port: 8001                # service针对内部请求监听的端口
    name: nginx-service-80
    protocol: TCP
    targetPort: 80          # pod应用的端口
    nodePort: 32001         # 针对外部请求的监听端口
  type: NodePort            # service type 类型: ClusterIP、NodePort、LoadBalancer、ExternalName
#--------------------------------------

# 创建service
kubectl apply -f /opt/yaml/service_nginx.yaml

$ service/nginx-app-service created

# 查看服务信息
kubectl get service -o wide
#----------------------------------------
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE     SELECTOR
kubernetes          ClusterIP   10.222.0.1       <none>        443/TCP          2d19h   <none>
nginx-app-service   NodePort    10.222.191.172   <none>        8001:32001/TCP   6m48s   app=nginx
#----------------------------------------

# 这里要注意的是 selector 的匹配, 如果匹配不到 通过 `get service` 信息是看不出来的;后面我们会详细了解一下如何查找是否创建一个"成功"的service
# 我们查看service describe 详情
kubectl describe service nginx-app-service
#----------------------------------------
Name:                     nginx-app-service
Namespace:                default
Labels:                   app=nginx-app
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.222.191.172
IPs:                      10.222.191.172
Port:                     nginx-service-80  8001/TCP
TargetPort:               80/TCP
NodePort:                 nginx-service-80  32001/TCP
Endpoints:                10.244.211.208:80,10.244.211.209:80,10.244.211.211:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
#----------------------------------------

服务创建成功了!我们访问测试下:

.105 Nginx

.106 Nginx

.107 Nginx

kube proxy 对node的负载是什么样的?

这里有个疑问:为什么通过三个NODE 都能访问到nginx 呢?kube proxy 如何做的负载?每个节点都能访问到我们创建的5个pod吗?

这个问题我们通过ipvs,得到了解答(需将iptable 升级为 ipvs)

我们运行ipvsadm 命令(在master和node节点上):

shell
# 在192.168.56.105节点上查看ipvs
ipvsadm -ln
#------------------------------
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
...
TCP  192.168.56.105:32001 rr
  -> 10.244.211.208:80            Masq    1      0          0
  -> 10.244.211.209:80            Masq    1      0          0
  -> 10.244.211.211:80            Masq    1      0          0
  -> 10.244.211.212:80            Masq    1      0          0
  -> 10.244.220.201:80            Masq    1      0          0
...
#------------------------------

# 在192.168.56.106节点上查看ipvs
ipvsadm -ln
#------------------------------
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
...
TCP  192.168.56.106:32001 rr
  -> 10.244.211.208:80            Masq    1      0          0
  -> 10.244.211.209:80            Masq    1      0          0
  -> 10.244.211.211:80            Masq    1      0          0
  -> 10.244.211.212:80            Masq    1      0          0
  -> 10.244.220.201:80            Masq    1      0          0
...
#------------------------------

通过查询出来的记录我们能很明确的知道:

访问k8s集群任意节点,都会将请求负载给deployment创建的所有pod上。

删除 service

shell
kubectl delete -n default service nginx-app-service

3. service type

service type 一览图

service 可以定义不同的type,最常用的是 ClusterIPNodePortLoadBalancer;

下面我们针对四种service type 进行了解

ClusterIP

类型为ClusterIP的service,这个service有一个Cluster-IP,其实就一个VIP。具体实现原理依靠kubeproxy组件,通过iptables或是ipvs实现。

这种类型的service 只能在

ClusterIP Shell

ClusterIP

NodePort

我们的场景不全是集群内访问,也需要。那么ClusterIP就满足不了了。NodePort当然是其中的一种实现方案。

在集群内部IP的基础上,在集群的每一个节点(NODE)端口上开放这个服务

NodePort Shell

NodePort 1

NodePort 2

此时我们可以通过http://4.4.4.1:30080或http://4.4.4.2:30080 对pod-python访问

LoadBalancer

LoadBalancer类型的service 是可以实现服务的另外一种解决方案。不过并不是所有的k8s集群都会支持,大多是在公有云托管集群中会支持该类型。

在使用一个集群内部IP地址和在NodePort上开放一个Service的基础上,还可以向云提供者申请一个负载均衡器,将流量转发到已经以NodePort形式开放的Service上。

在那些支持外部负载均衡器的云提供者上面,将type字段设置为"LoadBalancer"会为你的Service设置好一个负载均衡器。该负载均衡器的实际的创建是异步进行的,并且该设置好均衡器会在该Service的status.loadBalancer字段中显示出来

LoadBalancer Shell

LoadBalancer 1

loadBalancer和NodePort很相似,目的都是向外部暴露一个端口, 区别在于LoadBalancer会在 集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。

LoadBalancer 2

ExternalName

把集群外部的服务引入 集群内部,直接使用。

ExternalName类型的Service用于引入集群外部的服务,它通过externalName 属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。

ExternalName 1

ExternalName类型的Service用于引入集群外部的服务,它通过externalName 属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。

ExternalName 2

4. port、nodePort、targetPort、containerPort的区别

port

对内

k8s 集群内部访问 service的端口,即 通过 ClusterIP : port 去访问某个 Service

nodePort

对外

外部如果要访问 k8s 的 service,使用nodePort;即 通过NODE IP : nodePort 访问到某个Service

targetPort

对内

pod的端口,可理解为:"dockerfile 中的 expose"

一个请求 -> 经过 service -> service 根据 selector name 匹配 -> 转到pod name : targetPort

containerPort

对内

containerPort 是pod k8s对象yaml文件中 配置 暴露的端口。

通常情况下 可以认为:

containerPort == pod port;

containerPort == targetPort;

附录

参考资料

github kube-ladder

详解k8s的4种Service类型