Kubernetes(三)实战入门

实战入门

本章介绍如何在kubernetes集群中部署一个nginx服务,并能够对其进行访问。

 

1. Namespace

Namespace主要作用是实现多套环境的资源隔离或者多租户的资源隔离。

默认情况下,kubernetes 集群中的所有Pod都是可以相互访问的。但是在实际中,可能不希望让2个Pod之间进行相互访问,此时即可将两个Pod划分到不同的namespace下。Kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的“组”,以方便不同的组的资源进行隔离使用和管理。

可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理。这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等,来实现租户可用资源的管理。

例如可以给namespace-dev 的 ns 分配5GB的内存资源,而namespace-test 只分配3GB的资源。

 

Kubernetes集群在创建后,会默认创建几个namespaces:

$ kubectl get ns
NAME                     STATUS      AGE
default                  Active       22h   # 所有未指定Namespace的对象都会被分配在default 命名空间
kube-node-lease          Active       22h   # 集群节点之间的心跳维护,v1.13 开始引入
kube-public              Active       22h   # 此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system              Active       22h   # 所有由kubernetes 系统创建的资源都处于这个命名空间

 

下面是 namespaces 的资源操作示例:

# 查看
$ kubectl get ns kube-system
NAME          STATUS   AGE
kube-system   Active   23h

=> Active 表示命名空间正在使用;另一种状态是Terminating :表示正在删除命名空间

# 描述
$ kubectl describe ns default
Name:         default
Labels:       <none>
Annotations:  <none>
Status:       Active

No resource quota.   => ResourceQuota 针对namespace做的资源限制

No LimitRange resource.   => LimitRange 针对namespace中的每个组件做的资源限制


# 创建
$ kubectl create ns dev
namespace/dev created

# 删除
$ kubectl delete ns dev
namespace "dev" deleted

#配置方式
首先准备一个 yaml 文件:ds-dev.yaml
$ cat yamls/ns-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: dev

$ kubectl apply -f yamls/ns-dev.yaml
namespace/dev created

$ kubectl delete -f yamls/ns-dev.yaml
namespace "dev" deleted

2. Pod

Pod 是kubernetes集群进行管理的最小单元,程序要运行必须部署在container中,而container必须存在于Pod中。

Pod可以认为是container的封装,一个Pod中可以存在一个或多个container。如下图所示,默认会有一个根容器(也就是这里的Pause),此容器不会在 get pods 时显示给用户。

Kubernetes在集群启动后,集群中的各个组件也都是以Pod方式运行的。可以通过以下命令查看:

$ kubectl get pods -n kube-system
NAME                                        READY     STATUS        RESTARTS      AGE
aws-node-jtzb7                              1/1     Running           0            22h
coredns-74c8b6b7dd-7nhz8                    1/1     Running           0            23h
coredns-74c8b6b7dd-v6ztk               1/1     Running           0            23h
kube-proxy-lhd84                           1/1     Running           0            22h

 

此结果为 aws eks 集群的结果。在自建的eks集群中,一般还会有 etcd-master、kube-apiserver-master、kube-controller-manager-master、kube-scheduler-master 等 Pods。但是在 aws eks 中,客户端并无法显示这些pods。

另外的aws-node-jtzb7 与kube-proxy-lhd84均对应当前集群中的1个节点(当前集群仅有1个节点)。

 

Pod 操作

在创建并运行一个pod时,kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的:

# 命令格式:kubectl run (pod控制器名称) [参数]
# --image             指定Pod 镜像
# --port                指定服务暴露的端口
# --namespace   指定namespace

$ kubectl run nginx --image=nginx:1.17.1 --port=80 --namespace dev
pod/nginx created

$ kubectl get pods -o wide -n dev
NAME    READY   STATUS    RESTARTS   AGE     IP          NODE                                        NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          2m51s   10.0.1.84   ip-10-0-1-217.cn-north-1.compute.internal   <none>           <none>

=> 这个 ip 是Pod 的ip,并非节点 ip

# 查看更详细内容
kubectl describe pod nginx -n dev

如何访问到此nginx 服务?

首先在 kubectl get pods -o wide -n dev 的结果中,可以看到 pod 的ip 为 10.0.1.84。结合我们指定暴露的端口为 80,在访问时通过curl 10.0.1.84:80 访问即可。

 

创建pod与创建deployment的不同:

  1. kubectl run 一个pod后,一般会显示 pod/nginx created。此时创建的是单个pod,可以直接通过delete pod xxx 进行删除
  2. kubectl create deploy nginx --image=nginx:1.17.1 -n dev 会创建一个deployment,一般会显示deployment.apps/nginx created。此时创建的是一个deployment,直接删除一个pod 的话,会立即自动再创建一个pod。需要通过 $ kubectl delete deployment nginx -n dev 删除一个deployment,返回的结果是:deployment.apps "nginx" deleted

 

基于配置文件进行操作

创建一个pod-nginx.yaml,内容为:

apiVersion: v1
kind: Pod
metadata:
   name: nginx
   namespace: dev
spec:
   containers:
   - image: nginx:1.17.1
     imagePullPolicy: IfNotPresent
     name: pod
     ports:
     - name: nginx-port
       containerPort: 80
       protocol: TCP

 

创建:

$ kubectl create -f yamls/pod-nginx.yaml

pod/nginx created

 

删除:

$ kubectl delete -f yamls/pod-nginx.yaml

pod "nginx" deleted

 

3. Label

Label 是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。

Label的特点:

  1. 一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等
  2. 一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去
  3. Label 通常在资源对象定义时确定,当然也可以在对象创建后动态添加或删除

 

可以通过Label实现资源的多维度分组,以灵活、方便地进行资源分配、调度、配置、部署等管理工作。常用的Label如:

•    版本标签:"version":"release", "version":"stable"
•    环境标签:"environment":"dev", "environment":"test", "environment":"pro"
•    架构标签:"tier":"frontend", "tier":"backend"

在标签定义完毕后,还要考虑标签的选择,这时就要使用到Label Selector,即:

  • Label 用于给某个资源对象定义标识
  • Label Selector 用于查询和筛选拥有某些标签的资源对象

 

当前有2种Label Selector:

  1. 基于等式的Label Selector:name = slave
    • 选择所有包含 Label 中 key=”name” 且 value=”slave” 的对象;env != production:选择所有包含Label中key = “env” 且value !=”production” 的对象
  2. 基于集合的Label Selector:
    • name in (master, slave):选择所有包含Label中的key=”name” 且value=”master” 或 “slave” 的对象
    • name not in (frontend):选择所有包含Label中的key=”name” 且value不等于”frontend” 的对象

标签的选择条件可以使用多个,此时将多个Label Selector 进行组合,使用逗号“,” 进行分隔即可。例如:

name=slave, env!=production

name not in (frontend), env!=production

 

Label操作

命令方式:

# 为pod资源打标签
$ kubectl label pod nginx version=1.0 -n dev
pod/nginx labeled

$ kubectl label pod nginx -n dev tier=back
pod/nginx labeled

# 查看标签
$ kubectl get pod -n dev --show-labels
NAME    READY     STATUS       RESTARTS      AGE                LABELS
nginx         1/1       Running              0             6m2s      tier=back,version=1.0

# 为pod 资源更新标签
$ kubectl label pod nginx1 version=2.0 -n dev --overwrite
pod/nginx1 labeled

$ kubectl get pods -n dev --show-labels
NAME     READY   STATUS    RESTARTS   AGE   LABELS
nginx    1/1     Running   0          15m   tier=back,version=1.0
nginx1   1/1     Running   0          89s   run=nginx1,version=2.0

# 标签选择
$ kubectl get pods -l "version=2.0" -n dev --show-labels
NAME     READY   STATUS    RESTARTS   AGE   LABELS
nginx1   1/1     Running   0          2m    run=nginx1,version=2.0

# 删除标签
$ kubectl label pod nginx -n dev tier-
pod/nginx labeled

$ kubectl get pods -n dev --show-labels
NAME     READY   STATUS    RESTARTS   AGE     LABELS
nginx    1/1     Running   0          18m     version=1.0
nginx1   1/1     Running   0          4m10s   run=nginx1,version=2.0

 

以配置方式:

在yaml文件中加上label字段:

$ cat yamls/pod-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
   name: nginx
   namespace: dev
   labels:
     version: "3.0"
     tier: "production"
spec:
   containers:
   - image: nginx:1.17.1
     imagePullPolicy: IfNotPresent
     name: pod
     ports:
     - name: nginx-port
       containerPort: 80
       protocol: TCP

 

4. Deployment

在kubernetes 中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod资源出现故障时,会尝试进行重启或重建pod。

在kubernetes中Pod控制器的种类有很多,下面主要介绍其中一种:Deployment。

Deployment操作

命令方式:

# 创建
$ kubectl create deploy nginx-dep --image=nginx:1.17.1 -n dev
deployment.apps/nginx-dep created

# 查看
$ kubectl get deploy -n dev -o wide
NAME        READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-dep   1/1                           1            1           37s        nginx            nginx:1.17.1   app=nginx-dep

$ kubectl get pods -n dev --show-labels
NAME                         READY   STATUS    RESTARTS   AGE   LABELS
nginx-dep-74c95fbff9-lsngl   1/1     Running   0          19s   app=nginx-dep,pod-template-hash=74c95fbff9

=> 可以看到 deployment 有个SELECTOR 的标签选择器,选择的标签即为启动的pod自动打上的名称标签

# 删除
$ kubectl delete deploy nginx-dep -n dev
deployment.apps "nginx-dep" deleted

 

配置文件方式:

$ cat yamls/deploy-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
   name: nginx-dep
   namespace: dev
spec:
   replicas: 3
   selector:
      matchLabels:
         run: nginx
   template:
      metadata:
        labels:
          run: nginx
      spec:
        containers:
        - image: nginx:1.17.1
          name: nginx
          ports:
          - containerPort: 80
            protocol: TCP


selector 就是label选择器,pod哪里的label给予的是run:nginx
$ kubectl apply -f yamls/deploy-nginx.yaml
deployment.apps/nginx-dep created

$ kubectl get deploy -n dev
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-dep   3/3     3            3           103s

$ kubectl get pods -n dev
NAME                         READY   STATUS    RESTARTS   AGE
nginx-dep-755c49cf64-462g5   1/1     Running   0          2m21s
nginx-dep-755c49cf64-s74rx   1/1     Running   0          2m21s
nginx-dep-755c49cf64-sgc88   1/1     Running   0          2m21s

$ kubectl delete -f yamls/deploy-nginx.yaml

 

5. Service

现在我们可以通过deployment创建一组Pods,用于提供高可用服务。

但是,虽然每个Pod都会被分配一个单独的Pod IP,仍会存在以下2个问题:

  1. Pod IP会随着Pod的重建产生变化
  2. Pod IP仅是集群内可见的虚拟IP,外部无法访问

这样对于访问服务带来了难度。因此,kubernetes设计了Service来解决此问题。

Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以很方便地实现服务发现和负载均衡。

如下图所示:

 

 

一个请求在访问Service时,Service会通过标签选择器选择需要访问的Pod,然后将请求转发到对应的Pod中,其中也涉及负载均衡算法。Service在其整个生命周期中,IP地址都是不变的。

 

Service操作

创建集群内部可访问的Service

# 暴露Service
$ kubectl expose deploy nginx-dep --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev
service/svc-nginx1 exposed

此时暴露的是deployment,而不是直接1个pod。--port 指定的是 service 80 端口,转发到pod上的 80 端口(--terget-port=80)

# 查看Service
$ kubectl get svc -n dev
NAME         TYPE                CLUSTER-IP        EXTERNAL-IP   PORT(S)   AGE
svc-nginx1   ClusterIP    172.20.246.209         <none>        80/TCP    65s

# 由于指定的是ClusterIP,所以仅有集群内的节点能访问到此服务
# 通过 eks node 访问此地址:
$ curl 172.20.246.209<p><em>Thank you for using nginx.</em></p>
…

# 删除svc
$ kubectl delete svc svc-nginx2 -n dev
service "svc-nginx2" deleted

 

创建集群外部也能访问Service

# 若是需要外部也能访问,则需要修改type为NodePort
$ kubectl expose deploy nginx-dep --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev
service/svc-nginx2 exposed

$ kubectl get svc -n dev -o wide
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE     SELECTOR
svc-nginx1   ClusterIP   172.20.246.209   <none>        80/TCP         8m13s   run=nginx
svc-nginx2   NodePort    172.20.140.200   <none>        80:31890/TCP   18s     run=nginx
$ kubectl apply -f yamls/svc-nginx.yaml
service/svc-nginx created

$ kubectl delete -f yamls/svc-nginx.yaml
service "svc-nginx" deleted

 

posted @ 2021-03-10 11:09  ZacksTang  阅读(232)  评论(0编辑  收藏  举报