快速入门
前言
以下命令以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
# 创建nameSpace
kubectl create namespace curyu
# 简写
kubectl create ns curyu
$ namespace/curyu created
删除 nameSpace
# 删除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
字段设置重启策略:
- Always:只要退出就会重启。
- OnFailure:只有在失败退出(exit code不等于0)时,才会重启。
- 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
# 查看 `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
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
# 无论是pod、deployment、service 或是其他资源对象,都可以通过 `kubectl edit 资源类型 资源名称` 命令来进行修改。
kubectl edit pod pod-test
# 执行后会进入类似vim的页面(操作也和vim相似),我们移动光标到要修改的位置进行修改即可,修改完毕后 :wq保存,并且kubernetes会根据修改后的配置进行`自动升级、更新、启动`
删除 pod
# 同样的,删除命令也和修改命令类似,可以对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。
# 为了方便整理,我们把 所有与的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
# 通过pods `NAME` 删除 pod
kubectl delete deploy tomcat-test
$ pod "tomcat-test" deleted
# 除了通过`NAME` 删除,我门也可以通过 yaml 来删除
kubectl delete -f deployment_nginx.yaml
扩容缩容 pod
这里要注意的是:我在使用dashboard 进行 扩容、缩容操作时操作失败。
dashboard 提示操作的命令:
shellkubectl 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
# 我们可以通过命令去调整 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
# 为了方便整理,我们把 所有与的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>
#----------------------------------------
服务创建成功了!我们访问测试下:
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
kubectl delete -n default service nginx-app-service
3. service type
service 可以定义不同的type,最常用的是 ClusterIP
、NodePort
、LoadBalancer
;
下面我们针对四种service type 进行了解
ClusterIP
类型为ClusterIP的service,这个service有一个Cluster-IP,其实就一个VIP。具体实现原理依靠kubeproxy组件,通过iptables或是ipvs实现。
这种类型的service 只能在。
NodePort
我们的场景不全是集群内访问,也需要。那么ClusterIP就满足不了了。NodePort当然是其中的一种实现方案。
在集群内部IP的基础上,在集群的每一个节点(NODE)的端口上开放这个服务
此时我们可以通过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和NodePort很相似,目的都是向外部暴露一个端口, 区别在于LoadBalancer会在 集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
ExternalName
把集群外部的服务引入 集群内部,直接使用。
ExternalName类型的Service用于引入集群外部的服务,它通过externalName 属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
ExternalName类型的Service用于引入集群外部的服务,它通过externalName 属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
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
;