k8s 安装:https://www.cnblogs.com/jhxxb/p/14321352.html
yaml 文件说明:https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/kubernetes-objects
命名空间:https://kubernetes.io/zh/docs/tasks/administer-cluster/namespaces
一、使用任意端口暴露
sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml # 在 - --service-cluster-ip-range=10.96.0.0/16 下添加 - --service-node-port-range=1-65535 # 重启 kubelet sudo systemctl daemon-reload sudo systemctl restart kubelet
- targetPort:容器的端口(最根本的入口),与制作容器时暴露的端口一致(DockerFile中EXPOSE),也是 pod 的端口
- port:kubernetes 中服务之间访问的端口,service 的端口
- nodePort:外部可访问的端口。容器所在宿主机的端口(实质上也是通过 service 暴露给了宿主机,而 port 却没有)
- hostPort:通过宿主机的 IP:Port 来访问 Pod,和 nodePort 类似
nodePort 是集群外流量访问集群内服务的端口类型。Port 是集群内的 pod 互相通信用的端口类型。targetPort 是最终端口
二、常见应用
MySQL
随机端口,指定端口需要配置 nodePort,或者部署后是用 kubectl edit svc mysql-service 修改
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-mysql
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.74.2.71
path: "/nfs/mysql"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-mysql
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
spec:
selector:
matchLabels:
app: mysql-label
replicas: 1
template:
metadata:
labels:
app: mysql-label
spec:
containers:
- name: mysql
image: mysql:latest
env:
- name: MYSQL_ROOT_PASSWORD
value: root
- name: MYSQL_ROOT_HOST
value: '%'
- name: TZ
value: Asia/Shanghai
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: nfs-mysql
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql-label
type: NodePort
ports:
- port: 3306
targetPort: 3306
sudo mkdir /nfs/mysql
kubectl apply -f mysql.yaml
kubectl delete -f mysql.yaml
Oracle
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-oracle
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.74.2.71
path: "/nfs/oracle"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-oracle
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: oracle-deployment
spec:
selector:
matchLabels:
app: oracle-label
replicas: 1
template:
metadata:
labels:
app: oracle-label
spec:
containers:
- name: oracle-11g
image: loliconneko/oracle-ee-11g:latest
env:
- name: WEB_CONSOLE
value: 'false'
- name: DBCA_TOTAL_MEMORY
value: '4096'
ports:
- containerPort: 1521
volumeMounts:
- name: oracle-data
mountPath: /u01/app/oracle
volumes:
- name: oracle-data
persistentVolumeClaim:
claimName: nfs-oracle
---
apiVersion: v1
kind: Service
metadata:
name: oracle-service
spec:
selector:
app: oracle-label
type: NodePort
ports:
- port: 1521
targetPort: 1521
nodePort: 1521
sudo mkdir /nfs/oracle
kubectl apply -f oracle.yaml
Redis
注意这里 resources 项限制了 CPU 和 Memory 资源
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deployment
spec:
selector:
matchLabels:
app: redis-label
replicas: 1
template:
metadata:
labels:
app: redis-label
spec:
containers:
- name: redis
image: redis:alpine
resources:
limits:
cpu: 1
memory: 512Mi
requests:
cpu: 0.5
memory: 128Mi
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis-label
type: NodePort
ports:
- port: 6379
targetPort: 6379
nodePort: 6379
kubectl apply -f redis.yaml
Zentao(禅道)
https://hub.docker.com/r/easysoft/zentao
https://www.zentao.net/book/zentaopmshelp/40.html
apiVersion: v1
kind: PersistentVolume
metadata:
name: zentao-data
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.74.2.71
path: "/nfs/zentao"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zentao-data
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zentao-mysql-data
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.74.2.71
path: "/nfs/zentao-mysql"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zentao-mysql-data
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zentao-deployment
spec:
selector:
matchLabels:
app: zentao-label
replicas: 1
template:
metadata:
labels:
app: zentao-label
spec:
containers:
- name: zentao
image: easysoft/zentao:15.7
resources:
requests:
cpu: 2000m
memory: 2Gi
limits:
cpu: 2000m
memory: 2Gi
env:
- name: MYSQL_ROOT_PASSWORD
value: root
ports:
- name: zentao
containerPort: 80
- name: mysql
containerPort: 3306
volumeMounts:
- name: zentao-data
mountPath: /www/zentaopms
- name: zentao-mysql-data
mountPath: /var/lib/mysql
volumes:
- name: zentao-data
persistentVolumeClaim:
claimName: zentao-data
- name: zentao-mysql-data
persistentVolumeClaim:
claimName: zentao-mysql-data
---
apiVersion: v1
kind: Service
metadata:
name: zentao-service
spec:
selector:
app: zentao-label
type: NodePort
ports:
- name: mysql
port: 3306
targetPort: 3306
nodePort: 9595
- name: zentao
port: 80
targetPort: 80
nodePort: 9696
部署并修改远程连接可以数据库
sudo mkdir /nfs/zentao sudo mkdir /nfs/zentao-mysql sudo chown zhangsan:zhangsan -R /nfs/zentao/ sudo chown zhangsan:zhangsan -R /nfs/zentao-mysql/ kubectl apply -f zentao.yaml # 进入容器,修改配置 # https://mariadb.com/kb/en/configuring-mariadb-for-remote-client-access/ vim /etc/mysql/mariadb.conf.d/50-server.cnf #bind-address=127.0.0.1 skip-networking=0 skip-bind-address # 重启 mariadb 服务 cat /var/run/mysqld/mysqld.pid kill xxx service mysql restart # 查看监听地址 ss -an
Docker 镜像仓库
https://github.com/Joxit/docker-registry-ui/tree/main/examples/kubernetes
先创建 https 证书和密码文件:https://www.cnblogs.com/jhxxb/p/13637834.html
然后将文件创建成 ConfigMap:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-pod-configmap
kubectl create namespace devops kubectl -n devops create configmap registry-config-auth --from-file=/opt/registry/auth kubectl -n devops create configmap registry-config-certs --from-file=/opt/registry/certs
仓库使用 registry,UI 使用 joxit/docker-registry-ui,若出现 Access-Control-Allow-Origin 问题,看看配置:NGINX_PROXY_PASS_URL 为代理,REGISTRY_URL 为直接访问,二选一。若存储为本机可以将 nfs 改为 hostPath
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-docker-registry
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Delete # https://kubernetes.io/zh/docs/tasks/administer-cluster/change-pv-reclaim-policy/
nfs:
server: 10.74.2.71
path: /nfs/docker-registry # sudo chmod -R 0777 /nfs/docker-registry
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-docker-registry
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: docker-registry-deployment
spec:
selector:
matchLabels:
app: docker-registry-label
replicas: 1
template:
metadata:
labels:
app: docker-registry-label
spec:
containers:
- name: docker-registry
image: registry # 镜像版本
env:
- name: REGISTRY_STORAGE_DELETE_ENABLED
value: "true"
- name: REGISTRY_AUTH
value: htpasswd
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: basic-realm
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: /auth/htpasswd
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: /certs/domain.crt
- name: REGISTRY_HTTP_TLS_KEY
value: /certs/domain.key
ports:
- containerPort: 5000
protocol: TCP
volumeMounts:
- name: docker-registry-data
mountPath: /var/lib/registry
- name: docker-registry-auth
mountPath: /auth
- name: docker-registry-certs
mountPath: /certs
volumes:
- name: docker-registry-data
persistentVolumeClaim:
claimName: nfs-docker-registry # 将上面创建的 pv 关联到 pvc 上
- name: docker-registry-auth
configMap:
name: registry-config-auth # 关联到 configMap 上
- name: docker-registry-certs
configMap:
name: registry-config-certs
---
apiVersion: v1
kind: Service
metadata:
name: docker-registry-service
spec:
selector:
app: docker-registry-label
ports:
- targetPort: 5000
port: 5000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: docker-registry-ui-deployment
spec:
selector:
matchLabels:
app: docker-registry-ui-label
replicas: 1
template:
metadata:
labels:
app: docker-registry-ui-label
spec:
containers:
- name: docker-registry-ui
image: joxit/docker-registry-ui
env:
- name: DELETE_IMAGES
value: "true"
- name: SINGLE_REGISTRY
value: "true"
- name: PULL_URL
value: 10.74.2.71:5000
- name: NGINX_PROXY_PASS_URL # https://github.com/Joxit/docker-registry-ui/tree/main/examples
value: https://docker-registry-service:5000 # 若配置了 ca,这里为 https
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: docker-registry-ui-service
spec:
selector:
app: docker-registry-ui-label
ports:
- targetPort: 80
port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: docker-registry-ui-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
backend:
service:
name: docker-registry-ui-service
port:
number: 80
pathType: Prefix
host: registry.example.com
创建
sudo mkdir /nfs/docker-registry kubectl apply -f registry.yaml # 查看 kubectl get deployment -n docker-registry -o wide kubectl get pods -n docker-registry kubectl get svc -n docker-registry -o wide kubectl get ing -n docker-registry kubectl describe ingress docker-registry-ui-ingress -n docker-registry # 查看 ingress 对外端口 kubectl get svc -n ingress-nginx
访问 UI 要配置 Hosts 文件,端口为 ingress 的 80 对外端口
Jenkins
https://github.com/jenkinsci/kubernetes-plugin/blob/master/README_zh.md#在-kubernetes-中运行
PV 配置,VolumeClaimTemplates 匹配不上 PV 时会出现 StatefulSet 挂载不到 PV 的问题
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-home
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
nfs:
server: 10.74.2.71
path: /nfs/jenkins
若删除了 PVC,想让 PV 可以被重新绑定:https://stackoverflow.com/questions/58168408/kubernetes-pv-refuses-to-bind-after-delete-re-create
# 要再次让 PV Available,需删除 uid kubectl patch pv jenkins-home --type json -p '[{"op": "remove", "path": "/spec/claimRef/uid"}]' # 或删除整个 claimRef 部分 kubectl patch pv jenkins-home --type json -p '[{"op": "remove", "path": "/spec/claimRef"}]'
创建
# 创建 PV sudo mkdir /nfs/jenkins & sudo chmod -R 0777 /nfs/jenkins kubectl apply -f jenkins-pv.yaml # 创建名称空间 kubectl create namespace devops # 设置当前配置默认名称空间 kubectl config set-context $(kubectl config current-context) --namespace=devops # 创建 jenkins kubectl create -f http://raw.githubusercontent.com/jenkinsci/kubernetes-plugin/master/src/main/kubernetes/service-account.yml kubectl create -f http://raw.githubusercontent.com/jenkinsci/kubernetes-plugin/master/src/main/kubernetes/jenkins.yml # 查看网络,访问需要配置 hosts 文件:jenkins.example.com,使用 https 访问 kubectl describe services/jenkins # 设置当前配置默认名称空间 kubectl config set-context $(kubectl config current-context) --namespace=default
安装 Kubernetes 插件:https://plugins.jenkins.io/kubernetes
https://kubernetes.default.svc.cluster.local http://jenkins.devops.svc.cluster.local:80

关于地址命名,与 DNS 有关:https://kubernetes.io/zh/docs/concepts/services-networking/dns-pod-service
安装 Pipeline 插件,测试 Pipeline script,注意改 NFS 地址
def label = "mypod-${UUID.randomUUID().toString()}"
podTemplate(label: label, cloud: 'kubernetes', containers: [
containerTemplate(name: 'maven', image: 'maven:3.8.4-jdk-8', ttyEnabled: true, command: 'cat')
], volumes: [
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
nfsVolume(mountPath: '/root/.m2', serverAddress: '10.74.2.71', serverPath: '/nfs/maven')
])
{
node(label) {
stage('git') {
container('jnlp') {
sh 'git clone --branch master --depth 1 https://gitee.com/jhxxb/MySpringBoot.git'
}
}
stage('maven') {
container('maven') {
stage('maven install') {
sh """
cd MySpringBoot
mvn -B -DskipTests=true clean install
"""
}
stage('maven package') {
sh """
cd MySpringBoot
mvn -DskipTests=true package
"""
}
}
}
}
}
三、部署应用到指定 Node 节点
两种方式:NodeName 和 NodeSelector
一、NodeName
以部署 RabbitMQ 为例,注意 nodeName 属性值为节点名称
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabbitmq-deployment
spec:
selector:
matchLabels:
app: rabbitmq-label
replicas: 1
template:
metadata:
labels:
app: rabbitmq-label
spec:
nodeName: k8s-node-8
containers:
- name: rabbitmq
image: rabbitmq:management-alpine
resources:
limits:
cpu: 1
memory: 512Mi
requests:
cpu: 0.5
memory: 128Mi
env:
- name: RABBITMQ_DEFAULT_VHOST
value: my_vhost
- name: RABBITMQ_DEFAULT_USER
value: guest
- name: RABBITMQ_DEFAULT_PASS
value: guest
ports:
- containerPort: 5672
- containerPort: 15672
---
apiVersion: v1
kind: Service
metadata:
name: rabbitmq-service
spec:
selector:
app: rabbitmq-label
type: NodePort
ports:
- name: app
port: 5672
targetPort: 5672
nodePort: 5672
- name: ui
port: 15672
targetPort: 15672
nodePort: 15672
部署查看
kubectl apply -f rabbitmq.yaml
kubectl get pods -o wide
二、NodeSelector
给 Node 设置标签
kubectl label nodes k8s-node-8 deploy=hello kubectl get nodes --show-labels
已部署 MQ 为例,注意 nodeSelector 属性值为标签属性值
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabbitmq-deployment
spec:
selector:
matchLabels:
app: rabbitmq-label
replicas: 1
template:
metadata:
labels:
app: rabbitmq-label
spec:
nodeSelector:
deploy: hello
containers:
- name: rabbitmq
image: rabbitmq:management-alpine
resources:
limits:
cpu: 1
memory: 512Mi
requests:
cpu: 0.5
memory: 128Mi
env:
- name: RABBITMQ_DEFAULT_VHOST
value: my_vhost
- name: RABBITMQ_DEFAULT_USER
value: guest
- name: RABBITMQ_DEFAULT_PASS
value: guest
ports:
- containerPort: 5672
- containerPort: 15672
---
apiVersion: v1
kind: Service
metadata:
name: rabbitmq-service
spec:
selector:
app: rabbitmq-label
type: NodePort
ports:
- name: app
port: 5672
targetPort: 5672
nodePort: 5672
- name: ui
port: 15672
targetPort: 15672
nodePort: 15672
