### 部署 Kubernetes 应用
如何来部署一个原生的 Kubernetes 应用呢? 部署一个kubernetes 应用流程如下:
![](http://on-img.com/chart_image/5b84ad40e4b0d4d65be96283.png?_=1535509752205)
1. pull代码
2. 测试registry,并登陆registry.
3. 自动编写应用 Dockerfile
4. 构建打包 Docker 镜像
5. 应用maven 构建缓存
5. 推送 Docker 镜像到仓库
6. 更改 Deployment YAML 文件中参数
7. 利用 kubectl 工具部署应用
8. 检查应用状态
### 第一步,Pull 代码及全局环境变量申明
#!/bin/bash
# Filename: k8s-deploy_v0.2.sh
# Description: jenkins CI/CD 持续发布脚本
# Author: yi.hu
# Email: yi.hu@dianrong.com
# Revision: 1.0
# Date: 2018-08-10
# Note: prd
# zookeeper基础服务,依照环境实际地址配置
init() {
local lowerEnv="$(echo ${AppEnv} | tr '[:upper:]' 'lower')"
case "${lowerEnv}" in
dev)
CFG_ADDR="10.34.11.186:4181"
DR_CFG_ZOOKEEPER_ENV_URL="10.34.11.186:4181"
;;
demo)
CFG_ADDR="10.34.11.186:4181"
DR_CFG_ZOOKEEPER_ENV_URL="10.34.11.186:4181"
;;
*)
echo "Not support AppEnv: ${AppEnv}"
exit 1
;;
esac
}
# 函数执行
init
# 初始化变量
AppId=$(echo ${AppOrg}_${AppEnv}_${AppName} |sed 's/[^a-zA-Z0-9_-]//g' | tr "[:lower:]" "[:upper:]")
CFG_LABEL=${CfgLabelBaseNode}/${AppId}
CFG_ADDR=${CFG_ADDR}
VERSION=$(echo "${GitBranch}" | sed 's@release/@@')
### 第二步,登录harbor 仓库
docker_login () {
docker login ${DOCKER_REGISTRY} -u${User} -p${PassWord}
}
### 第三步,编译代码,制作应用镜像,上传镜像到harbor仓库。
build() {
if [ "x${ACTION}" == "xDEPLOY" ] || [ "x${ACTION}" == "xPRE_DEPLOY" ]; then
echo "Test harbor registry: ${DOCKER_REGISTRY}"
curl --connect-timeout 30 -I ${DOCKER_REGISTRY}/api/projects 2>/dev/null | grep 'HTTP/1.1 200 OK' > /dev/null
echo "Check image EXIST or NOT: ${ToImage}"
ImageCheck_Harbor=$(echo ${ToImage} | sed 's/\([^/]\+\)\([^:]\+\):/\1\/api\/repositories\2\/tags\//')
Responed_Code=$(curl -u${User}:${PassWord} -so /dev/null -w '%{response_code}' ${ImageCheck_Harbor} || true)
echo ${Responed_Code}
if [ "${NoCache}" == "true" ] || [ "x${ResponedCode}" != "x200" ] ; then
if [ "x${ActionAfterBuild}" != "x" ]; then
eval ${ActionAfterBuild}
fi
echo "生成Dockerfile文件"
echo "FROM ${FromImage}" > Dockerfile
cat >> Dockerfile <<-EOF
${Dockerfile}
EOF
echo "同步上层镜像: ${FromImage}"
docker pull ${FromImage} # 同步上层镜像
echo "构建镜像,并Push到仓库: ${ToImage}"
docker build --no-cache=${NoCache} -t ${ToImage} . && docker push ${ToImage} || exit 1 # 开始构建镜像,成功后Push到仓库
echo "删除镜像: ${ToImage}"
docker rmi ${ToImage} || echo # 删除镜像
fi
fi
}
### 第四步,发布、预发布、停止、重启
deploy() {
if [ "x${ACTION}" == "xSTOP" ]; then
# 停止当前实例
kubectl delete -f ${AppName}-deploy.yaml
elif [ "x${ACTION}" == "xRESTART" ]; then
kubectl delete pod -n ${NameSpace} -l app=${AppName}
elif [ "x${ACTION}" == "xDEPLOY" ]; then
kubectl apply -f ${AppName}-deploy.yaml
fi
}
### 第五步,查看pod 是否正常启动,如果失败则返回1,进而会详细显示报错信息。
check_status() {
RETRY_COUNT=5
echo "检查 pod 运行状态"
while (( $RETRY_COUNT )); do
POD_STATUS=$(kubectl get pod -n ${NameSpace} -l app=${AppName} )
AVAILABLE_COUNT=$(kubectl get deploy -n ${NameSpace} -l app=${AppName} | awk '{print $(NF-1)}' | grep -v 'AVAILABLE')
if [ "X${AVAILABLE_COUNT}" != "X${Replicas}" ]; then
echo "[$(date '+%F %T')] Show pod Status , wait 30s and retry #$RETRY_COUNT "
echo "${POD_STATUS}"
let RETRY_COUNT-- || true
sleep 30
elif [ "X${AVAILABLE_COUNT}" == "X${Replicas}" ]; then
echo "Deploy Running successed"
break
else
echo "[$(date '+%F %T')] NOT expected pod status: "
echo "${POD_STATUS}"
return 1
fi
done
if [ "X${RETRY_COUNT}" == "X0" ]; then
echo "[$(date '+%F %T')] show describe pod status: "
echo -e "`kubectl describe pod -n ${NameSpace} -l app=${AppName}`"
fi
}
#主流程函数执行
docker_login
build
### 第六步, 更改 YAML 文件中参数
cat > ${WORKSPACE}/${AppName}-deploy.yaml <<- EOF
#####################################################
#
# ${ACTION} Deployment
#
#####################################################
apiVersion: apps/v1beta2 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
name: ${AppName}
namespace: ${NameSpace}
labels:
app: ${AppName}
version: ${VERSION}
AppEnv: ${AppEnv}
spec:
replicas: ${Replicas}
selector:
matchLabels:
app: ${AppName}
template:
metadata:
labels:
app: ${AppName}
spec:
containers:
- name: ${AppName}
image: ${ToImage}
ports:
- containerPort: ${ContainerPort}
livenessProbe:
httpGet:
path: ${HealthCheckURL}
port: ${ContainerPort}
initialDelaySeconds: 90
timeoutSeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: ${HealthCheckURL}
port: ${ContainerPort}
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 5
# configmap env
env:
- name: CFG_LABEL
value: ${CFG_LABEL}
- name: HTTP_SERVER
value: ${HTTP_SERVER}
- name: CFG_ADDR
value: ${CFG_ADDR}
- name: DR_CFG_ZOOKEEPER_ENV_URL
value: ${DR_CFG_ZOOKEEPER_ENV_URL}
- name: ENTRYPOINT
valueFrom:
configMapKeyRef:
name: ${ConfigMap}
key: ENTRYPOINT
- name: HTTP_TAR_FILES
valueFrom:
configMapKeyRef:
name: ${ConfigMap}
key: HTTP_TAR_FILES
- name: WITH_SGHUB_APM_AGENT
valueFrom:
configMapKeyRef:
name: ${ConfigMap}
key: WITH_SGHUB_APM_AGENT
- name: WITH_TINGYUN
valueFrom:
configMapKeyRef:
name: ${ConfigMap}
key: WITH_TINGYUN
- name: CFG_FILES
valueFrom:
configMapKeyRef:
name: ${ConfigMap}
key: CFG_FILES
# configMap volume
volumeMounts:
- name: applogs
mountPath: /volume_logs/
volumes:
- name: applogs
hostPath:
path: /opt/app_logs/${AppName}
imagePullSecrets:
- name: ${ImagePullSecrets}
---
apiVersion: v1
kind: Service
metadata:
name: ${AppName}
namespace: ${NameSpace}
labels:
app: ${AppName}
spec:
ports:
- port: ${ContainerPort}
targetPort: ${ContainerPort}
selector:
app: ${AppName}
EOF
### 第七步,创建configmap 环境变量
kubectl delete configmap ${ConfigMap} -n ${NameSpace}
kubectl create configmap ${ConfigMap} ${ConfigMapData} -n ${NameSpace}
# 执行部署
deploy
# 打印配置
cat ${WORKSPACE}/${AppName}-deploy.yaml
# 执行启动状态检查
check_status
- 云原生应用
- 容器化微服务改造方案
- 应用容器化上线规范
- 服务网格和传统应用区别
- DevOps 管理规范
- 基础架构管理规范
- 域名管理规范
- 主机名称管理规范
- 应用域名管理规范
- 应用上线规范
- GIT分支及API JAR上传规范
- 基础架构设计
- 运维管理职责
- 基础服务
- DNS 内部架构
- centos 及 kernel 版本标准
- Linux服务器OS标准配置
- Docker版本初始化
- kuberneter 集群方案
- kubernetes 命名规范
- Jenkins CI/CD
- nginx 配置文件变更流程
- Prometheus 容器监控
- 项目资源需求
- 应用服务
- 编译和运行期标准
- 新核心系统基础服务架构
- 安全防御
- 互联网软件可靠性工程及可靠性度量