通过本篇文章记录如何在Kubernetes集群中部署一个nginx服务,并且能够对其进行访问
Namespace是Kubernetes系统中的一种非常重要的资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离
默认情况下,Kubernetes集群中的所有Pod都是可以相互访问的,但是我们再实际过程中很可能不想让两个Pod之间进行相互的访问,那么此时就可以将两个Pod划分到不同的namespace下。Kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的“组”,以方便不同的组的资源进行隔离使用和管理。(多套环境资源隔离)
可以通过Kubernetes的授权机制,将不同的Namespace交给不同的租户进行管理,这样就实现了多租户的资源隔离。此时还能结合Kubernetes的资源配额机制,限定不同租户所能占用的资源,例如CPU的使用量,内存的使用量等等,以实现租户可用资源的管理。(多租户的资源隔离)
在Kubernetes集群启动之后,是会默认创建几个Namespace的
[root@master ~]# kubectl get ns
NAME STATUS AGE
default Active 2d19h #所有未指定Namespace的对象都会被分配在default空间
kube-node-lease Active 2d19h #集群节点之间的心跳维护,从v1.13开始引入
kube-public Active 2d19h #此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system Active 2d19h #所有由Kubernetes系统创建的资源都处于这个命名空间
下面可以来看看Namespace资源的具体操作:
# 1、查看所有Namespace
[root@master ~]# kubectl get ns
NAME STATUS AGE
default Active 2d19h
dev Active 19h
kube-node-lease Active 2d19h
kube-public Active 2d19h
kube-system Active 2d19h
# 2、查看指定的Namespace 命令:kubectl get ns
[root@master ~]# kubectl get ns dev
NAME STATUS AGE
dev Active 19h
# 3、指定输出格式 命令:kubectl get ns -o <格式参数>
# Kubernetes支持的格式有很多,比较常见的是wide、JSON、yaml
[root@master ~]# kubectl get ns dev -o yaml
apiVersion: v1
kind: Namespace
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{},"name":"dev"}}
creationTimestamp: "2022-04-06T10:44:40Z"
labels:
kubernetes.io/metadata.name: dev
name: dev
resourceVersion: "91162"
uid: c8973639-a1ed-4a50-a83e-93ea9f5c53a3
spec:
finalizers:
- kubernetes
status:
phase: Active
# 4、查看ns详情 命令:kubectl describe ns
[root@master ~]# kubectl describe ns dev
Name: dev
Labels: kubernetes.io/metadata.name=dev
Annotations:
Status: Active # Active是命名空间正在使用中 Terminating:正在删除命名空间
# ResourceQuota 针对namespace做的资源限制
# LimitRange针对namespace中的每个组件做的资源限制
No resource quota.
No LimitRange resource.
创建
创建namespace
[root@master ~]# kubectl create ns dev namespace/dev created
删除namespace
[root@master ~]# kubectl delete ns dev namespace "dev" deleted
Pod是Kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而且容器必须存在于Pod中。Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。
Kubernetes在集群启动之后,集群中的各个组件也是以Pod方式运行的可以通过下面的命令进行查看:
[root@master ~]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-68845d5dc9-8t42r 1/1 Running 1 (5h21m ago) 27h
calico-node-f64nf 1/1 Running 1 (5h21m ago) 27h
calico-node-gx9rm 1/1 Running 1 (5h21m ago) 27h
calico-node-mh2s9 1/1 Running 1 (5h21m ago) 27h
coredns-6d8c4cb4d-ndjfj 1/1 Running 1 (5h21m ago) 2d22h
coredns-6d8c4cb4d-sfkhv 1/1 Running 1 (5h21m ago) 2d22h
etcd-master 1/1 Running 7 (5h21m ago) 2d22h
kube-apiserver-master 1/1 Running 12 (5h21m ago) 2d22h
kube-controller-manager-master 1/1 Running 6 (5h21m ago) 2d22h
kube-flannel-ds-66plh 1/1 Running 2 (5h19m ago) 27h
kube-flannel-ds-76qlm 1/1 Running 2 (5h19m ago) 27h
kube-flannel-ds-xcwdf 1/1 Running 1 (5h21m ago) 27h
kube-proxy-gtfkb 1/1 Running 4 (5h21m ago) 2d22h
kube-proxy-nzrf5 1/1 Running 4 (5h21m ago) 2d22h
kube-proxy-trd4z 1/1 Running 4 (5h21m ago) 2d22h
kube-scheduler-master 1/1 Running 7 (5h21m ago) 2d22h
[root@master ~]#
创建并运行
Kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来进行实现的
# 命令格式:kubectl run <参数>
# --image 指定Pod的镜像
# --port 指定端口
# --namespace 指定namespace
[root@master ~]# kubectl run nginx --image=nginx:1.17.3 --port=80 -n dev
pod/nginx created
#查看pod的详细信息 -o wide
[root@master ~]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 4m59s 10.244.169.135 k8s-node2
# 查看更加详细的关于Pod的描述
[root@master ~]# kubectl describe pods nginx -n dev
Name: nginx
Namespace: dev
Priority: 0
Node: k8s-node2/192.168.88.102
Start Time: Thu, 07 Apr 2022 18:12:27 +0800
Labels: run=nginx
Annotations: cni.projectcalico.org/containerID: 468f473e2f618ebfdefde078143e5585c406ae553c6ef72e9bb832dddb2cb465
cni.projectcalico.org/podIP: 10.244.169.136/32
cni.projectcalico.org/podIPs: 10.244.169.136/32
Status: Running
IP: 10.244.169.136
IPs:
IP: 10.244.169.136
Containers:
nginx:
Container ID: docker://582fc46f31c50a0c154a81af05f6f1e762a12a4d2fc80e5df2a14a499580a0d6
Image: nginx:1.17.3
Image ID: docker-pullable://nginx@sha256:9688d0dae8812dd2437947b756393eb0779487e361aa2ffbc3a529dca61f102c
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 09 Apr 2022 10:10:02 +0800
Last State: Terminated
Reason: Error
Exit Code: 255
Started: Thu, 07 Apr 2022 18:12:31 +0800
Finished: Sat, 09 Apr 2022 10:09:07 +0800
Ready: True
Restart Count: 1
Environment:
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-xwb7n (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-xwb7n:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional:
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors:
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 40h default-scheduler Successfully assigned dev/nginx to k8s-node2
Normal Pulled 40h kubelet Container image "nginx:1.17.3" already present on machine
Normal Created 40h kubelet Created container nginx
Normal Started 40h kubelet Started container nginx
Normal SandboxChanged 4m6s (x3 over 4m34s) kubelet Pod sandbox changed, it will be killed and re-created.
Normal Pulled 4m5s kubelet Container image "nginx:1.17.3" already present on machine
Normal Created 4m4s kubelet Created container nginx
Normal Started 4m4s kubelet Started container nginx
访问Pod
# 首先可以查询一下Pod的IP地址
[root@master ~]# kubectl get pods -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 1 (43m ago) 40h 10.244.169.136 k8s-node2
#然后使用curl命令进行访问
[root@k8s-node2 ~]# curl 10.244.169.137:80
Welcome to nginx!
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.
Thank you for using nginx.
删除Pod
# 先使用get命令看看空间里面运行的Pod [root@master ~]# kubectl get pod -n dev NAME READY STATUS RESTARTS AGE nginx 1/1 Running 2 (6h58m ago) 2d2h # delete命令删除想要删除的命令?试试先 [root@master ~]# kubectl delete pod nginx -n dev pod "nginx" deleted # 去看看有没有删除成功 [root@master ~]# kubectl get pod -n dev No resources found in dev namespace.
kubectl delete这个命令在新版的里面是可以直接删除Pod的 因为新版本不会自动创建Deployment了 但是在老版的里面只会重启Pod,所以在老版本里面需要这个后台(deployment)给直接干掉,所以我现在再重新创建一个Pod,再使用删除deployment的方法删除Pod。
在这个过程中我发现了一个问题,就是我在自己创建的namespace中新建pod之后,是看不到ns中有deployment的,然后在我去掉了-n dev之后,发现在default空间中有一个deployment,是我之前运行在default中的nginx,然后我使用delete命令删除这个pod,就出现了我之前提过的在老版的k8s中的情况:
[root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-85b98978db-n2rfw 1/1 Running 4 (102m ago) 5d1h [root@master ~]# ^C [root@master ~]# kubectl delete pod nginx-85b98978db-n2rfw pod "nginx-85b98978db-n2rfw" deleted [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-85b98978db-qhz7j 0/1 ContainerCreating 0 5s
然后试试用删除deployment的方法:
[root@master ~]# kubectl delete deployment nginx deployment.apps "nginx" deleted [root@master ~]# kubectl get pod No resources found in default namespace. [root@master ~]#
只要deployment没了,Pod也就消失了这就是怎么样删除一个带有Pod控制器的pod。新版本的run会直接通过Controller创建一个pod,不会创建deployment对象
Label是Kubernetes系统中的一个重要概念,它的作用就是在资源上添加标识,用来对他们进行区分和选择。Label的特点:
● 一个Label会以key/value的键值对的形式附加到各种对象上,如Node、Pod、Service
● 一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源上去
● Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除
可以通过Label实现资源的多维度分组,以便灵活、方便的进行资源分配、调度、配置、部署等管理工作。
一些常用的Label示例如下:
● 版本标签:“version”:“release”,“version”:“stable”...
● 环境标签:“environment”:“dev”,“environment”:“test”,“environment”:“pro”
● 架构标签:“tier”:“fronted”,“tier”:“backend”
标签定义完毕之后还要考虑到标签的选择,这就要用到Label Selector,即:
Label用于给某个资源对象定义标识
Label Selector用于查询和筛选拥有某些标签的资源对象
当前有两种Label Selector:
● 基于等式的Label Selector
name = salve :选择所有包含Label中key=“name”且value="salve"的对象
env !=production:选择所有包括Label中的key=“env”且value不等于production的对象
● 基于集合的Label Selector
name in (master,salve) : 选择所有包含Label中的key=“name”且value=“master”或“salve”的对象
name not in (fronted) :选择所有包含Label中的key="name"且value不等于fronted的对象
标签的选择条件可以使用多个,此时将多个Label Selector进行组合,使用逗号进行分隔即可。例如:
name=slave,env!=production
name not in (fronted),env!=production
命令方式
# 为Pod资源打标签
[root@master ~]# kubectl label pod nginx version=1.0 -n dev
pod/nginx labeled
# 为Pod资源更新标签
[root@master ~]# kubectl label pod nginx version=2.0 -n dev --overwrite
pod/nginx labeled
# 查看标签
[root@master ~]# kubectl get pod nginx -n dev --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 1 (11h ago) 13h run=nginx,version=2.0
# 筛选标签
[root@master ~]# kubectl get pod -n dev -l version=2.0 --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 1 (11h ago) 13h run=nginx,version=2.0
[root@master ~]# kubectl get pod -n dev -l version!=2.0 --show-labels
No resources found in dev namespace.
# 删除标签(使用的是打标签的方式,在想要删除的标签后面打上减号)
[root@master ~]# kubectl label pod nginx -n dev version-
pod/nginx unlabeled
[root@master ~]# kubectl get pod -n dev -l version!=2.0 --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 1 (11h ago) 13h run=nginx
配置方式
# 首先创建一个YAML文件
apiVersion: v1
kind: Pod
metadata:
name: nginx1
namespace: dev
#这里打两个标签
labels:
version: "3.0"
env: "test"
spec:
containers:
- image: nginx:1.71.1
name: pod
ports:
- name: nginx1-port
containerPort: 80
protocol: TCP
[root@master ~]# kubectl apply -f nginx1.yaml
pod/nginx1 created
[root@master ~]# kubectl get pod -n dev --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 1 (13h ago) 15h run=nginx
nginx1 1/1 Running 0 114s env=test,version=3.0
在Kubernetes,Pod是最小的控制单元,但是Kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于Pod的管理,确保Pod资源符合预期的状态,当Pod资源出现故障时,会尝试进行重启或重建Pod。
在Kubernetes中Pod控制器的种类有很多,这里先介绍一种:Deployment
命令操作
# 命令格式 :kubectl create deploy '
# --image 指定pod的镜像
# --port 指定端口
# --replicas 指定创建pod的数量
# --namespace 指定namespace
[root@master ~]# kubectl create deploy nginx --image=nginx --port=80 --replicas=3 -n dev
deployment.apps/nginx created
[root@master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 1 (15h ago) 17h
nginx-74d589986c-bsv2h 1/1 Running 0 47s
nginx-74d589986c-nxv5d 1/1 Running 0 47s
nginx-74d589986c-tbpv2 1/1 Running 0 47s
可以看到dev中已经新建了三个新的nginx的pod,查看一下这个deployment
[root@master ~]# kubectl describe deployment nginx -n dev
Name: nginx
Namespace: dev
CreationTimestamp: Sun, 10 Apr 2022 14:15:09 +0800
Labels: app=nginx
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:
Mounts:
Volumes:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets:
NewReplicaSet: nginx-74d589986c (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 6m8s deployment-controller Scaled up replica set nginx-74d589986c to 3
# 删除这个deployment
[root@master ~]# kubectl delete deploy nginx -n dev
deployment.apps "nginx" deleted
[root@master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 1 (16h ago) 18h
配置操作
创建一个deploy-nginx.yaml 内容如下
apiVersion : apps/v1
kind : Deployment
metadata:
name: nginx
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
protocol: TCP
[root@master ~]# kubectl create -f deploy-nginx.yaml
deployment.apps/nginx created
[root@master ~]# vi deploy-nginx.yaml
[root@master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 1 (17h ago) 19h
nginx-69ccc6c65-4tw7n 1/1 Running 0 3m18s
nginx-69ccc6c65-7sw85 1/1 Running 0 3m18s
nginx-69ccc6c65-hv5bq 1/1 Running 0 3m18s
nginx1 1/1 Running 0 3h40m
[root@master ~]# kubectl get deploy -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 3m28s
虽然每个Pod都会被分配一个单独的Pod IP,然而却存在着如下的两个问题:
● Pod IP会随着Pod的重建产生变化
● Pod IP仅仅只是集群内可见的虚拟IP,外部无法访问
这样对于访问这个服务就带来了困难,也正因如此,Kubernetes设计了Service来解决这个问题。Service可以看做是一组同类Pod对外的访问接口。借助Service,应用可以方便的实现服务发现和负载均衡
Service作为对外访问的接口,收到一个请求后,直接到达Service上,Service再根据标签选择器去寻找对应的Pod。
操作一:创建集群内部可访问的Service
# 暴露Service 指定名称、类型、端口号、目标端口号(从Service的80端口转发的pod的80端口) [root@master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev service/svc-nginx1 exposed
现在就可以直接通过Service的IP:端口来对里面的Pod进行访问了
[root@master ~]# kubectl get svc -n dev NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc-nginx1 ClusterIP 10.110.30.14
80/TCP 5m45s [root@master ~]# curl 10.110.30.14:80 Welcome to nginx! Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.Thank you for using nginx.
操作二:创建集群外部也可访问的Service
上面创建的Service的type类型为ClusterIP,这个IP地址只有集群内部可以进行访问,如果需要创建集群外部也可以进行访问的Service,需要修改type为NodePort
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev service/svc-nginx2 exposed [root@master ~]# kubectl get svc -n dev NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc-nginx1 ClusterIP 10.110.30.14
80/TCP 33m svc-nginx2 NodePort 10.110.131.245 80:31431/TCP 25s 这里,访问主机的相应端口号:192.168.88.100:31431
删除Service
[root@master ~]# kubectl delete svc svc-nginx2 -n dev
service "svc-nginx2" deleted