技术标签: 云原生 kubernetes Docker 容器
1、准备好三台虚拟机(基于VMWare centos7)
【临时关闭】
systemctl stop fire walld
【永久关闭】
systemctl disable firewalld
【永久关闭】
sed -i 's/enforcing/disabled/' '/etc/selinux/config'
临时关闭
setenforce 0
【临时关闭】
swapoff -a
【永久关闭】
sed -ri 's/.*swap.*/#&/' /etc/fstab
hostnamectl set-hostname <hostname>
比如设置名字
k8master
k8node1
k8node2
cat >> /etc/hosts<<EOF
192.168.12.151 k8node2
192.168.12.152 k8node1
192.168.12.153 k8master
EOF
cat >/etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
EOF
yum install -y ntpdate
ntpdate time.windows.com
2、每台机器安装 docker、kubeadmin、kubelet,建立起集群
第一步:先搞docker:
docker安装
注意还要把 docker.serivce 加入到开机启动:
systemctl enable docker.service
第二步:还是添加个阿里云的yum源【master work 都要搞】
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
第三步:再装kubeadmin 、kubeadmin 、kubectl 【master work 都要装】
yum install -y kubelet-1.18.0
yum install -y kubeadm-1.18.0
yum install -y kubectl-1.18.0
systemctl enable kubelet
【设置了开机启动】
第四步:部署k8 master节点(在k8master节点上执行初始化动作)
这里的 192.168.12.153 是我本地虚拟机的 ip,即master
kubeadm init \
--apiserver-advertise-address=192.168.12.153 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.18.0 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.244.0.0/16
等到第四步执行完,这个过程会比较久,它会把master node上所需要的scheduler 、 apiserver 等N多东西拉取下来(如果不是阿里云的镜像,估计根本没法玩。。)等到出现下面的语句时就表示执行成功了
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.12.153:6443 --token b4ee7o.2d8puhdflaonjq38 \
--discovery-token-ca-cert-hash sha256:16526f83d2ae995ab96544b4f355ec5e3cba4cacc334c67035afa27e0ea9088d
第五步: 上面一步的执行结果中已经说明了下一步的动作。
配置:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
第六步:部署work node节点,将其 join到集群中来 【注意:要在work node执行】
kubeadm join 192.168.12.153:6443 --token b4ee7o.2d8puhdflaonjq38 \
--discovery-token-ca-cert-hash sha256:16526f83d2ae995ab96544b4f355ec5e3cba4cacc334c67035afa27e0ea9088d
这里的token是24H后失效,但可以重新生成:
kubeadm token create --print-join-command
做到这里,看看 此时状态–> NotReady
[root@k8master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8master NotReady master 9h v1.18.0
k8node1 NotReady <none> 54s v1.18.0
k8node2 NotReady <none> 39s v1.18.0
第七步:部署CNI网络插件,否则没法联网 【在master上执行】
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
不过这个地址要翻墙,有点麻烦。可以先下载下来【点此查看】,然后执行
kubectl apply -f kube-flannel.yml
第八步:查看此时 pod 的状态
[root@k8master ~]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7ff77c879f-px8zm 1/1 Running 0 10h
coredns-7ff77c879f-tqtjt 1/1 Running 0 10h
etcd-k8master 1/1 Running 1 10h
kube-apiserver-k8master 1/1 Running 1 10h
kube-controller-manager-k8master 1/1 Running 1 10h
kube-flannel-ds-hzks4 1/1 Running 0 83m
kube-flannel-ds-kcpk9 1/1 Running 0 83m
kube-flannel-ds-mflpz 1/1 Running 0 83m
kube-proxy-rggn5 1/1 Running 1 10h
kube-proxy-rz5b4 1/1 Running 0 106m
kube-proxy-w5rfq 1/1 Running 0 106m
kube-scheduler-k8master 1/1 Running 1 10h
第九步:安装一个Nginx 来做个测试(主要看网络有没问题)
kubectl create deployment nginx --image=nginx
获取到镜像可能需要时间,可以 不断 执行下面命令查看状态
kubectl get pod
kubectl expose deployment nginx --port=80 --type=NodePort
【查看Pod状态,注意这里是 逗号】
kubectl get pod,svc
[root@k8master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-f89759699-pchp4 1/1 Running 0 20m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 10h
service/nginx NodePort 10.1.114.75 <none> 80:31787/TCP 16m
通过浏览器访问:
http://192.168.12.151:31787/
OR:
http://192.168.12.152:31787/
由于K8做了LB,任意一个Work Node 的节点都可以访问到 Nginx的欢迎页面。
TODO
单节点集群:一个控制节点和一个工作节点,是个玩具。
最小的生产环境集群:至少三个节点,包括一个控制节点和两个工作节点,提供一定程度的高可用性和容错性。
建议的生产环境集群:至少三个控制节点(master)和三个worker node,可根据需求和负载进行扩展
基本格式: kubectl [command] [type] [name] [flags]
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-f89759699-pchp4 1/1 Running 0 51m
帮助命令:
kubectl help
【Kubectl 的命令 特别多,需要的时候直接查阅 帮助文档即可】kubectl get --help
【看 get 的细致命令】查看 健康检查:
kubectl get cs
yml文件格式:
---
表示一个新yml 的开始yml文件我们基本不从0开始写,而是生成一个模板,然后自己改改。
kubectl create deployment web --image=nginx -o yaml --dry-run > myyaml.yaml
这里创建一个 资源名为web的部署,但是并不真正执行,而只是 产生一个 yaml, --dry-run 表示 尝试运行;生成的yaml 内容输出到 一个文件
[root@k8master ~]# cat myyaml.yaml
# 版本
apiVersion: apps/v1
# 资源类型
kind: Deployment
# 资源元数据
metadata:
creationTimestamp: null
labels:
app: web
name: web
# 资源规格
spec:
# 副本数量
replicas: 1
# 标签选择器
selector:
matchLabels:
app: web
strategy: {}
# pod 模板
template:
# pod 元数据
metadata:
creationTimestamp: null
labels:
app: web
# pod规格
spec:
# 容器配置
containers:
- image: nginx
name: nginx
resources: {}
status: {}
kubectl get deploy nginx -o=yaml > myyaml2.yaml
创建容器使用Docker,一个Docker对应一个容器,一个容器里只有一个进程(多进程似乎也能实现,但不好管理),一个容器运行一个程序
Pod 为方便管理,将多个容器放在一起。Pod是多进程设计。
Pod存在是为了亲密性应用: 两个应用之间需要频繁调用。应用由于在同一网络中,调用性能更好、当然也更方便。
两个大机制:共享网络+共享存储 。
首先看第一点:
再看第二点:共享存储
就是 volume 数据卷的作用了
1、镜像拉取
2、资源限制
3、 重启策略
K8 的hc 是 容器对应用的hc,如此hc 有个问题:比如Java应用,已经堆溢出了,已不能提供服务,但是进程还在,容器不能准确获取状态。有一种更好的思路是通过检查应用状态来获取准确状态
先看 这里: 这个Pod是怎么 在 k8node1 上创建的呢?
比如:
resources:
requests:
memory:'64Mi'
cpu:'250m'
说明了宿主机必须满足剩余memory 64M,CPU 0.25C才会被调度到
比如yml 有这么一段描述:指定了Pod应该在 env_role=dev的Node上
下面简单描述一下 nodeSelector怎么对 env_role 起作用。Node1 Node2 属于dev ,Node3 Node4属于prod,可以调度Pod在 prod 环境中落地。这个场景对多环境的支持很有用。日常开发中常会切换dev qa staging等多个环境,但可能只要一套k8就将所有主机管理起来了。
那如何打标签呢?
[root@k8master ~]# kubectl label node k8node1 env_role=dev
node/k8node1 labeled
[root@k8master ~]# kubectl get nodes k8node1 --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8node1 Ready <none> 47h v1.18.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8node1,kubernetes.io/os=linux
默认已经打了很多标签了。env_role只是一个标签名,我们可以打自定义的标签,比如 kubectl label node k8node foo=bar
nodeAffinity
,和nodeSelector
实现方式一致,使用labels
来影响调度。nodeAffinity
支持运算符操作,支持两种 亲和性(硬 、软)。常用operator: In NotIn Exists Gt Lt DoesnotExist
。
比如, 在nodeSelector
中,要求调度到env_role=dev
的节点,若有该label
的节点不存在,将会一直等待。使用nodeAffinity(软)
,我们可以设定优先调度到 env_role=dev
,若没有,调度到env_role=qa 也可以。
也有所谓的反亲和性,截图中使用的是 operator :In,如果是 NotIn DoesnotExist
,就是反亲和。
p.s. 英语中的 affinity 表示一种亲密程度,也常见词,翻译成了汉语之后,总感觉有点过于高大上了,尽管它表达的是很简单的含义。
NodeSelector NodeAffinity 都是Pod的属性,在调度的时候实现。
污点:不是Pod的属性,而是节点的属性,规定哪些节点不做普通分配调度。
使用场景:
演示:
[root@k8master ~]# kubectl describe node k8master |grep taint -i
Taints: node-role.kubernetes.io/master:NoSchedule
这里是master:NoSchedule;K8中的污点值的枚举(三个):
如何打上污点呢?
kubectl taint node [node] key=value:污点枚举值
kubectl taint node [node] key=value:污点枚举值 -
举个栗子:
// 创建 nginx 应用
[root@k8master ~]# kubectl create deployment web --image=nginx
deployment.apps/web created
//看此时pods
[root@k8master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-f89759699-pchp4 1/1 Running 0 2d11h 10.244.1.2 k8node1 <none> <none>
web-5dcb957ccc-2gbcj 1/1 Running 0 40s 10.244.2.2 k8node2 <none> <none>
// 再部署多一个nginx (名字叫 web)
kubectl create deployment web --image=nginx
// 再跟着扩容一个
kubectl scale deployment web --replicas=2
// 此时再看 pod情况
[root@k8master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-f89759699-pchp4 1/1 Running 0 2d11h 10.244.1.2 k8node1 <none> <none>
web-5dcb957ccc-2gbcj 1/1 Running 0 9m13s 10.244.2.2 k8node2 <none> <none>
web-5dcb957ccc-8wnn4 1/1 Running 0 2m56s 10.244.1.3 k8node1 <none> <none>
// 看到 Pod在Node上:
无论是 k8node1 k8node2都有分布。
// 删除当前的 Pods
[root@k8master ~]# kubectl delete deployment nginx
[root@k8master ~]# kubectl delete deployment web
// 所有pod 已经删除完了
[root@k8master ~]# kubectl get pods -o wide
No resources found in default namespace.
// 给 k8node1 打上污点
[root@k8master ~]# kubectl taint node k8node1 env_role=dev:NoSchedule
node/k8node1 tainted
// 确认已经打上了污点
[root@k8master ~]# kubectl describe node k8node1 |grep -i taint
Taints: env_role=dev:NoSchedule
// 创建并扩容
[root@k8master ~]# kubectl create deployment web --image=nginx
deployment.apps/web created
[root@k8master ~]# kubectl scale deployment web --replicas=2
deployment.apps/web scaled
// 可以看到 所有的容器都部署到了 k8node2 ,k8node1 由于已经打上了污点,因此不会被调度到
[root@k8master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-5dcb957ccc-ph7kd 1/1 Running 0 116s 10.244.2.4 k8node2 <none> <none>
web-5dcb957ccc-wtmcz 1/1 Running 0 2m14s 10.244.2.3 k8node2 <none> <none>
// 再来删除污点 【注意最后的 横杠 - 】
[root@k8master ~]# kubectl taint node k8node1 env_role:NoSchedule-
node/k8node1 untainted
[root@k8master ~]# kubectl describe node k8node1 |grep taint -i
Taints: <none>
污点容忍:
即使设置了污点值为 NoSchedule,这个Node依然可能被调度到。
Pod是一种 抽象; Controller 是具体存在的。
controller:
第一步: 先生成一个测试用的模板 yml:
W0309 22:37:13.728646 40038 helpers.go:553] --dry-run is deprecated and can be replaced with --dry-run=client.
[root@k8master ~]# cat web.yml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
第二步:部署
由于是测试,不需要改了,然后从这个yaml 部署:
[root@k8master ~]# kubectl apply -f web.yml
deployment.apps/web created
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-5dcb957ccc-cfbw4 1/1 Running 0 13s
第三步: 暴露端口 (使用yml的方式)
// 生成暴露端口的yml
[root@k8master ~]# kubectl expose deployment web --port=80 --target-port=80 --type=NodePort --name=web1 -o yaml>web1.yml
// 看下web1.yml内容
[root@k8master ~]# cat service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
status:
loadBalancer: {}
//应用yml暴露端口
[root@k8master ~]# kubectl apply -f web1.yml
// 查看是否暴露成功
[root@k8master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-5dcb957ccc-cfbw4 1/1 Running 0 5m11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 2d23h
service/web1 NodePort 10.1.72.70 <none> 80:31800/TCP 63s
// 从浏览器访问
OK
小结一下就是:
生成拉起容器yml --> 部署(拉起容器) --> 生成暴露端口 yml --> apply
roll : ngnix 1.14 --> 1.15
roll back: nginx :1.15--> 1.14
升级和回滚,不过回滚未必是从高版本–> 低版本,而是从当前版本–> 上一个版本。这里明白就好,不纠结。
k8可以使用yml 描述 升级和回滚的 行为:
(还是上一节生成的yml)
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
# 【这里改为 2】
replicas: 2
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
# 【原本这里未指定版本因此使用了latest 版本,现在改为 1.14】
- image: nginx:1.14
name: nginx
resources: {}
status: {}
现在我们来升级一下 nginx 版本, nginx :1.15
// 通过 kubectl set image 来设定镜像版本
[root@k8master ~]# kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated
[root@k8master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-65b7447c7-k5z87 0/1 Terminating 0 5m14s 10.244.1.5 k8node1 <none> <none>
web-65b7447c7-wr9k8 1/1 Running 0 5m14s 10.244.2.6 k8node2 <none> <none>
web-7d9697b7f8-6h4b6 0/1 ContainerCreating 0 2s <none> k8node2 <none> <none>
web-7d9697b7f8-ln4bb 1/1 Running 0 36s 10.244.1.6 k8node1 <none> <none>
// 看下 升级的状态
[root@k8master ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
看 升级的过程也挺有意思:先拉起一个容器,然后再销毁之前的容器。
如果此时我还是觉得之前的版本更好,想要还原回去;首先看下之前使用过哪些版本; 然后回滚到上一个版本(绝大多数场景下都是回滚到上一个版本)
// 看到目前只有过 2 个版本
[root@k8master ~]# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
[root@k8master ~]# kubectl rollout undo deployment web
deployment.apps/web rolled back
[root@k8master ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
// 回滚是个相当快的操作!!!
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-65b7447c7-9gxlr 1/1 Running 0 30s
web-65b7447c7-q7qx2 1/1 Running 0 27s
// 还可以回滚到指定的版本【注意后面的 --to-revision=2】:
[root@k8master ~]# kubectl rollout undo deployment web --to-revision=2
deployment.apps/web rolled back
[root@k8master ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-7d9697b7f8-qls7t 1/1 Running 0 15s
web-7d9697b7f8-s8cvk 1/1 Running 0 17s
弹性伸缩:
// 【将副本数修改为 5 个 (伸)】
[root@k8master ~]# kubectl scale deployment web --replicas=5
deployment.apps/web scaled
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-7d9697b7f8-5t8kp 1/1 Running 0 6s
web-7d9697b7f8-5ts25 1/1 Running 0 6s
web-7d9697b7f8-pmckl 1/1 Running 0 6s
web-7d9697b7f8-qls7t 1/1 Running 0 2m9s
web-7d9697b7f8-s8cvk 1/1 Running 0 2m11s
// 【将副本数 修改为 2 个(缩)】 (伸缩的过程极快)
[root@k8master ~]# kubectl scale deployment web --replicas=2
deployment.apps/web scaled
[root@k8master ~]#
[root@k8master ~]#
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-7d9697b7f8-pmckl 1/1 Running 0 102s
web-7d9697b7f8-qls7t 1/1 Running 0 3m45s
Service: 定义一组Pod的访问规则。
1、 为何需要service 这层抽象?
2、Service 和Pod 如何产生联系?
答曰:通过 labels & selector.
pod 具有 labels ;
serivce 有 selector:
serivce 使用 selector 来pick 哪些 pod 作为一组服务。
通过service实现服务注册和发现
3、常见service类型
先来看个例子:
kubectl expose --help
--type='': Type for this service: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.
这里看出来 service 的几种类型: clusterIP 、NodePort、LoadBalancer。
看下效果:
kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml
kubectl apply -f web.yaml
kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service.yaml
// service中没有指定service 类型,则按 ClusterIP 处理
kubectl apply -f service.yaml
// 现在来看下pods,svc:
[root@k8master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/web-5dcb957ccc-mprzn 1/1 Running 0 10m
pod/web-5dcb957ccc-s4jg8 1/1 Running 0 10m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 4d8h
service/web ClusterIP 10.1.143.33 <none> 80/TCP 2m38s
这里的 TYPE \ CLUSTER-IP 10.1.143.33 就是 前面说的用于集群内的service 类型,来测试下:
[root@k8master ~]# curl 10.1.143.33
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
.....
// 接着修改 service.yaml ; 增加了 service 类型为NodePort ;同时将 name 改为 web1(防止冲突)
[root@k8master ~]# cat service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web1
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}
// 再来看此时 pods svc
[root@k8master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/web-5dcb957ccc-mprzn 1/1 Running 0 17m
pod/web-5dcb957ccc-s4jg8 1/1 Running 0 17m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 4d8h
service/web ClusterIP 10.1.143.33 <none> 80/TCP 10m
service/web1 NodePort 10.1.128.23 <none> 80:30762/TCP 87s
发现多出了一个service Type: NodePort,我们可从浏览器访问:
http://192.168.12.151:30762/ ,访问OK
无状态:
状态:
什么叫 无头 的?
其实说白了:ClusterIP=None的service,取而代之的是 域名,即:通过域名来操作。
比如说,正常情况下是 有头的 service。
[root@k8master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 6d12h
web ClusterIP 10.1.143.33 <none> 80/TCP 2d3h
web1 NodePort 10.1.128.23 <none> 80:30762/TCP 2d3h
1、准备个yml
[root@k8master ~]# cat sts.yml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
apps: nginx
spec:
ports:
- port: 80
name: web
# 这里就是设置的无头的Service
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: nginx
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
2、查看此时pods,svc
// 可以看到 : 有三个POD,每个都是唯一的名称
[root@k8master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-statefulset-0 1/1 Running 0 31s
pod/nginx-statefulset-1 1/1 Running 0 27s
pod/nginx-statefulset-2 1/1 Running 0 23s
// 【下面的 Service/Nginx 是无头的的service】
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 7d8h
service/nginx ClusterIP None <none> 80/TCP 3m24s
前面提到: StatefulSet 的POD有唯一的网络标识,因此和Deployment相比,POD是有身份的。那域名怎么定义的呢?
答曰: 根据主机名,并根据一定规则生成域名
ngnix-statefulset-0.nginx.default.svc.cluster.local
特点:在每个Node节点上,运行同一个POD。新加入的Node,也加入这个POD。
这种部署方式十分常见:
做个演示:
1、准备yml
[root@k8master ~]# cat ds.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: mydaemonset
labels:
app: filebeat
spec:
selector:
matchLabels:
app: filebeat
template:
metadata:
labels:
app: filebeat
spec:
containers:
- name: logs
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: varlog
mountPath: /tmp/log
volumes:
- name: varlog
hostPath:
path: /var/log
2、查看
[root@k8master ~]# kubectl apply -f ds.yml
[root@k8master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mydaemonset-cl847 1/1 Running 0 28s 10.244.2.16 k8node2 <none> <none>
mydaemonset-vwk8v 1/1 Running 0 28s 10.244.1.17 k8node1 <none> <none>
// 去看一下创建的 daemonset ,果然里面有很多的日志了
[root@k8master ~]# kubectl exec -it mydaemonset-cl847 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@mydaemonset-cl847:/# ls /tmp/log/
anaconda btmp dmesg maillog-20210307 rhsm spooler-20210314 vmware-network.log
......
首先,创建yml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl","-Mbignum=bpi","-wle","print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
然后启动任务:
[root@k8master ~]# kubectl create -f job.yml
若果本地没有镜像,首先要拉取镜像,会比较慢;过了一段时间后,注意这里的状态,是 Completed,表示已经完成了;还可以 kubectl logs PODNAME
查看日志。
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pi-5x67j 0/1 Completed 0 3m4s
[root@k8master ~]# kubectl logs pi-5x67j
3.14159...
[root@k8master ~]# cat cronjob.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo hello from K8S cluster
restartPolicy: OnFailure
[root@k8master ~]# kubectl apply -f cronjob.yml
//等待一段时间后;可见,这个cron job ,每分钟都会起一个容器,执行完之后,就销毁容器!!!
[root@k8master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-1616077920-2vf94 0/1 Completed 0 2m39s
hello-1616077980-4tvdx 0/1 Completed 0 99s
hello-1616078040-4t2bt 0/1 Completed 0 39s
部署无状态: Deployment
部署有状态: StatefulSet
部署 Job: Job
部署CronJob: CronJob
部署守护进程: DaemontSet
文章浏览阅读408次。 在ubuntu 8.04下安装Oracle 11g2008年05月22日 星期四 11:02oracle 11g 数据库虽然提供了linux x86的版本,但是支持的linux版本只有Red Hat,Novell and Solaris 这几个,debian 和 ubuntu 不在支持之列,所以在ubuntu下安装就相对麻烦一些,请照着下文的方法一步一步的安装,不
文章浏览阅读166次。新东方在线中考网整理了《初一英语下册语法知识点全汇总》,供同学们参考。一. 情态动词can的用法can+动词原形,它不随主语的人称和数而变化。1. 含有can的肯定句:主语+can+谓语动词的原形+其他。2. 含有can的否定句:主语+can't+动词的原形+其他。3. 变一般疑问句时,把can提前:Can+主语+动词原形+其他? 肯定回答:Yes,主语+can。否定回答:No,主语+can't...._七年级下册计算机知识点
文章浏览阅读3k次。在平时开发中,可能会遇到UFUN函数没有的功能,比如创建PTP的加工程序(我目前没找到,哪位大神可以指点一下),可以使用Grip创建PTP,然后用UFUN函数UF_call_grip调用Grip程序。具体如下截图(左侧UFUN,右侧Grip程序):..._uf调用grip
文章浏览阅读156次。第一个:原生普通样式(随着主题不同,样式会变)第二个:原生普通样式-小icon第三个:自定义RatingBar 颜色第四个:自定义RatingBar DrawableRatingBar 各样式实现===============原生样式原生样式其实没什么好说的,使用系统提供的style 即可<RatingBarstyle="?android:attr/ratingBarStyleIndicator"android:layout_width=“wrap_cont.._ratingbar样式修改
文章浏览阅读4.6k次,点赞6次,收藏11次。安装vs2017:参考vs2017下载和安装。安装cmake3.12.3:cmake是一个工程文件生成工具。用户可以使用预定义好的cmake脚本,根据自己的选择(像是Visual Studio, Code::Blocks, Eclipse)生成不同IDE的工程文件。可以从它官方网站的下载页上获取。这里我选择的是Win32安装程序,如图所示:然后就是运行安装程序进行安装就行。配置glfw3...._vs2017的opengl环境搭建(完整篇)
文章浏览阅读976次。MLC NAND,UBIFS_ubifs warning
文章浏览阅读2.2k次。计算机系统的两种存储器形式介绍时间:2016-1-6计算机系统的存储器一般应包括两个部分;一个是包含在计算机主机中的主存储器,简称内存,它直接和运算器,控制器及输入输出设备联系,容量小,但存取速度快,一般只存放那些急需要处理的数据或正在运行的程序;另一个是包含在外设中的外存储器,简称外存,它间接和运算器,控制器联系,存取速度虽然慢,但存储容量大,是用来存放大量暂时还不用的数据和程序,一旦要用时,就..._计算机存储器系统采用的是主辅结构,主存速度快、容量相对较小,用于 1 分 程序,外
文章浏览阅读5.6k次。1. STEP 7(Simatic Manager):STEP 7或者Simatic Manager是西门子PLC编程最常用的软件开发环境。4. STEP 7 MicroWin:STEP 7 MicroWn是一款专门针对微型PLC(S7-200系列PLC)的编程软件,是Simatic Manager的简化版。如果需要与PLC系统配合使用,则需要与PLC编程工具进行配合使用。除了上述软件之外,西门子还提供了一些配套软件和工具,如PLC模拟器、硬件调试工具等,以帮助PLC编程人员快速地进行调试和测试。_西门子plc编程软件
文章浏览阅读36次。【代码】HashMap扩容。_hashma扩容
文章浏览阅读2.9k次。1mvn dependency:copy-dependencies2 项目右键 -> Maven -> Disable Maven Nature3 项目右键 -> Configure -> Convert to Maven Project_maven资源加载不全,怎么重新加载
文章浏览阅读527次。DMLDML的全称是Database management Language,数据库管理语言。主要包括以下操作:insert、delete、update、optimize。本篇对其逐一介绍INSERT数据库表插入数据的方式:1、insert的完整语法:(做项目的过程中将字段名全写上,这样比较容易看懂)单条记录插入语法:insert into table_name (column_name1,......_dml的全称是
文章浏览阅读136次。可以参考: http://git.oschina.net/jrain-group/ 组织下的Java Modbus支持库Modbus-系列文章1、虚拟成对串口(1)下载虚拟串口软件VSPD(可在百度中搜索)image.png(2)打开软件,添加虚拟串口。在设备管理中,看到如下表示添加成功。..._最好用的 modebus调试工具