在前面,我们大概讲解了Kubernetes包含的组件,今天,我们就来详细讲解一下这些组件的作用与使用
Pod
在Kubernetes中,最小的管理元素不是一个个独立的容器,而是Pod,Pod是最小的,管理,创建,计划的最小单元.
使用方法
1.创建一个pod的yaml文件,名称为nginx_pod.yaml
apiVersion: v1 // 版本号
kind: Pod //类别
metadata:
name: nginx-pod //Pod名称
labels:
app: nginx //Pod label
spec:
containers: //容器
- name: nginx-container //容器名称
image: nginx //镜像
ports:
- containerPort: 80 //端口号
2.根据该nginx_pod.yaml文件创建pod
kubectl apply -f nginx_pod.yaml
3.查看
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 29s
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-pod 1/1 Running 0 40m 192.168.80.194 w2
kubectl describe pod nginx-pod
Name: nginx-pod
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: w2/192.168.0.62
Start Time: Sun, 06 Oct 2019 20:45:35 +0000
Labels: app=nginx
Annotations: cni.projectcalico.org/podIP: 192.168.80.194/32
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-pod","namespace":"default"},"spec":{"c...
Status: Running
IP: 192.168.80.194
Containers:
nginx-container:
Container ID: docker://eb2fd0b2906f53e9892e22a6fd791c9ac68fb8e5efce3bbf94ec12bae96e1984
Image: nginx
Image ID: docker-pullable:/
4.删除
kubectl delete -f nginx_pod.yaml
ReplicationController(RC)
Replication Controller 就像一个进程管理器,监管着不同node上的多个pod,而不是单单监控一个node上的pod,Replication Controller 会委派本地容器来启动一些节点上服务(Kubelet ,Docker)
ReplicationController定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包含以下几个部分:
- Pod期待的副本数(replicas)
- 用于筛选目标Pod的Label Selector
- 当Pod的副本数量小于预期数量时,用于创建新Pod的Pod模板(template)
也就是说通过RC实现了集群中Pod的高可用,减少了传统IT环境中手工运维的工作
使用方法
1.创建名为nginx_replication.yaml
apiVersion: v1
kind: ReplicationController //表示要新建对象的类型
metadata:
name: nginx
spec:
replicas: 3 //Pod期待的副本数
selector:
app: nginx //表示需要管理的Pod的label,这里表示包含app: nginx的label的Pod都会被该RC管理
template: //表示用于定义Pod的模板,比如Pod名称、拥有的label以及Pod中运行的应用等
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
2.根据nginx_replication.yaml创建pod
kubectl apply -f nginx_replication.yaml
3.查看
kubectl get pods -o wide
NAME READY STATUS
nginx-hksg8 1/1 Running 0 44s 192.168.80.195 w2
nginx-q7bw5 1/1 Running 0 44s 192.168.190.67 w1
nginx-zzwzl 1/1 Running 0 44s 192.168.190.68 w1
kubectl get rc
NAME DESIRED CURRENT READY AGE
nginx 3 3 3 2m54s
4.扩容
kubectl scale rc nginx --replicas=5
kubectl get pods
nginx-8fctt 0/1 ContainerCreating 0 2s
nginx-9pgwk 0/1 ContainerCreating 0 2s
nginx-hksg8 1/1 Running 0 6m50s
nginx-q7bw5 1/1 Running 0 6m50s
nginx-wzqkf 1/1 Running 0 99s
5.删除
kubectl delete -f nginx_replication.yaml
ReplicaSet(RS)
在Kubernetes v1.2时,RC就升级成了另外一个概念:Replica Set,官方解释为“下一代RC”
ReplicaSet和 Replication Controller之间的唯一区别是现在的选择器支持。Replication Controller只支持基于等式的selector(env=dev或environment!=qa),但ReplicaSet还支持新的,基于集合的selector(version in (v1.0, v2.0)或env notin (dev, qa))
在试用时官方推荐ReplicaSet
注意:一般情况下,我们很少单独使用Replica Set,它主要是被Deployment这个更高的资源对象所使用,从而形成一整套Pod创建、删除、更新的编排机制。当我们使用Deployment时,无须关心它是如何创建和维护Replica Set的,这一切都是自动发生的。同时,无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment支持)。
使用方法
1.创建frontend.yaml
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector: //选择器,可以使用IN
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
resources:
requests:
cpu: 100m
memory: 100Mi
env: //环境设置
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
2.根据frontend.yaml创建pod
kubectl create -f frontend.yaml
3.查看
kubectl get pods
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
kubectl describe rs/frontend
Name: frontend
Namespace: default
Image(s): gcr.io/google_samples/gb-frontend:v3
Selector: tier=frontend,tier in (frontend)
Labels: app=guestbook,tier=frontend
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l
4.删除
kubectl delete -f frontend.yaml
Deployment
Deployment为Pod和Replica Set(下一代Replication Controller)提供声明式更新。
Deployment为Pod和ReplicaSet提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController来方便的管理应用。典型的应用场景包括:
- 定义Deployment来创建Pod和ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续Deployment
使用方法
1.创建nginx_deployment.yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels: //匹配的模板
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
2.根据nginx_deployment.yaml文件创建pod
kubectl apply -f nginx_deployment.yaml
3.扩容
kubectl scale deployment nginx-deployment --replicas 10
4.更新
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
5.回滚
kubectl rollout undo deployment/nginx-deployment
Namespace
Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是属于某一个namespace的(默认是default),而node, persistentVolumes等则不属于任何namespace。
Namespace常用来隔离不同的用户,比如Kubernetes自带的服务一般运行在kube-system namespace中
使用方法
1.创建myns-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: myns
2.根据myns-namespace.yaml创建namespace
kubectl apply -f myns-namespace.yaml
3.查询
kubectl get namespaces
NAME STATUS AGE
default Active 38m
kube-system Active 38m
myns Active 6s
4.指定空间
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: myns
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
5.删除
kubectl delete namespaces myns-namespace
Network
Network 提供了基于策略的网络控制,用于隔离应用并减少攻击面
1.同一个Pod中container之间的通信
每个pod中都会有一个pause container,所有创建的container都会链接到它上面,从而实现网络互通
2.同一个集群Pod之间
我们先来看一个例子:
准备两个Pod,一个nginx,一个busybox
nginx_pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
busybox_pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
运行并查看情况
kubectl apply -f nginx_pod.yaml
kubectl apply -f busybox_pod.yaml
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
busybox 1/1 Running 0 49s 192.168.221.70 worker02-kubeadm-k8s
nginx-pod 1/1 Running 0 7m46s 192.168.14.1 worker01-kubeadm-k8s
接下来,我们分别测试两种不同场景下它们之间能否通信
1.同一台Node
来到worker01:ping 192.168.14.1
PING 192.168.14.1 (192.168.14.1) 56(84) bytes of data.
64 bytes from 192.168.14.1: icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from 192.168.14.1: icmp_seq=2 ttl=64 time=0.048 ms
2.不同的Node
来到worker02:ping 192.168.14.1
PING 192.168.14.1 (192.168.14.1) 56(84) bytes of data.
64 bytes from 192.168.14.1: icmp_seq=1 ttl=63 time=0.680 ms
64 bytes from 192.168.14.1: icmp_seq=2 ttl=63 time=0.306 ms
64 bytes from 192.168.14.1: icmp_seq=3 ttl=63 time=0.688 ms
我们发现,无论是同一台Node还是不同的Node之间都是可以相互通信的,这得益于网络插件calico,为每个Pod都生成了一个Ip,且只限于集群内使用
但有一个坏处就是:每个Pod是不稳定的,比如通过Deployment管理的Pod,随时可能对Pod进行扩容或删减,从而导致Pod的Ip不断变化
这时,就需要一个固定的Ip,使得集群内方便使用
Service
Kubernete Service 是一个定义了一组Pod的策略的抽象,我们也有时候叫做宏观服务。这些被服务标记的Pod都是(一般)通过label Selector决定的
使用Kubernetes,您无需修改应用程序即可使用不熟悉的服务发现机制。 Kubernetes为Pods提供自己的IP地址和一组Pod的单个DNS名称,并且可以在它们之间进行负载平衡
我们先来看下Service的几种类型:
Cluster IP
顾名思义。就是集群内部使用的IP
1.创建whoami-deployment.yaml文件,并且apply
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-deployment
labels:
app: whoami
spec:
replicas: 3
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: jwilder/whoami
ports:
- containerPort: 8000
2.创建whoami的service
kubectl expose deployment whoami-deployment
3.查看
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19h
whoami-deployment ClusterIP 10.105.147.59 <none> 8000/TCP 23s
4.访问
[root@master-kubeadm-k8s ~]# curl 10.105.147.59:8000
I'm whoami-deployment-678b64444d-b2695
5.查看service的详情
kubectl describe svc whoami-deployment
Name: whoami-deployment
Namespace: default
Labels: app=whoami
Annotations: <none>
Selector: app=whoami
Type: ClusterIP
IP: 10.105.147.59
Port: <unset> 8000/TCP
TargetPort: 8000/TCP
Endpoints: 192.168.14.8:8000,192.168.221.81:8000,192.168.221.82:8000
Session Affinity: None
Events: <none>
发现有一个Endpoints连接了具体3个Pod,从而实现集群内的通信
NodePort
顾名思义,就是给每个Node暴露出一个端口,让集群外的服务可以访问集群内的Pod
1.创建Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-deployment
labels:
app: whoami
spec:
replicas: 3
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: jwilder/whoami
ports:
- containerPort: 8000
2.创建NodePort类型的service
kubectl expose deployment whoami-deployment --type=NodePort
3.查看
[root@master-kubeadm-k8s ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21h
whoami-deployment NodePort 10.99.108.82 <none> 8000:32041/TCP 7s
注意上述的端口32041,实际上就是暴露在集群中物理机器上的端口
4.访问
浏览器通过物理机器的IP访问http://192.168.0.51:32041
NodePort虽然能够实现外部访问Pod的需求,但是真的好吗?其实不好,占用了各个物理主机上的端口,所以,一般生产环境上不建议使用
HostPort
与NodePort作用类似,都是暴露主机上的任何可用端口,方便外部访问,与NodePort不同的是:HostPort只会为当前机器生成一个端口
Ingress
通常情况下,service和pod的IP仅可在集群内部访问。集群外部的请求需要通过负载均衡转发到service在Node上暴露的NodePort上,然后再由kube-proxy将其转发给相关的Pod。
而Ingress就是为进入集群的请求提供路由规则的集合
Ingress可以给service提供集群外部访问的URL、负载均衡、SSL终止、HTTP路由等。为了配置这些Ingress规则,集群管理员需要部署一个Ingress controller,它监听Ingress和service的变化,并根据规则配置负载均衡并提供访问入口
Ingress提供了很多的解决方案,今天,我们以Nginx Ingress Controller为例,来讲讲Ingress的使用
使用方法
1.创建tomcat-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deployment
labels:
app: tomcat
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containerPort: 8080
2.创建tomcat-service.yaml
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: tomcat
type: NodePort
3.安装Nginx Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/cloud/deploy.yaml
4.创建nginx-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
spec:
rules: //nginx.conf配置规则
- host: tomcat.jack.com
http:
paths:
- path: /
backend:
serviceName: tomcat-service
servicePort: 80
5.修改win的hosts文件,添加dns解析
192.168.8.61 tomcat.jack.com
6.访问
打开浏览器,访问tomcat.jack.com
大致的流程图如下: