DKube/service/deployment.go
2022-09-25 21:10:52 +08:00

292 lines
8.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"encoding/json"
"errors"
"github.com/wonderivan/logger"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"strconv"
"time"
)
var Deployment deployment
type deployment struct{}
type DeploymentsResp struct {
Items []appsv1.Deployment `json:"items"`
Total int `json:"total"`
}
type DeployCreate struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Replicas int32 `json:"replicas"`
Image string `json:"image"`
Label map[string]string `json:"label"`
Cpu string `json:"cpu"`
Memory string `json:"memory"`
ContainerPort int32 `json:"container_port"`
HealthCheck bool `json:"health_check"`
HealthPath string `json:"health_path"`
}
type DeploysNp struct {
Namespace string `json:"namespace"`
DeployNum int `json:"deployment_num"`
}
//获取deployment列表支持过滤、排序、分页
func (d *deployment) GetDeployments(filterName, namespace string, limit, page int) (deploymentsResp *DeploymentsResp, err error) {
deploymentList, err := K8s.ClientSet.AppsV1().Deployments(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
logger.Error(errors.New("获取Deployment列表失败, " + err.Error()))
return nil, errors.New("获取Deployment列表失败, " + err.Error())
}
selectableData := &dataSelector{
GenericDataList: d.toCells(deploymentList.Items),
DataSelect: &DataSelectQuery{
Filter: &FilterQuery{Name: filterName},
Paginate: &PaginateQuery{
Limit: limit,
Page: page,
},
},
}
filtered := selectableData.Filter()
total := len(filtered.GenericDataList)
data := filtered.Sort().Paginate()
deployments := d.fromCells(data.GenericDataList)
return &DeploymentsResp{
Items: deployments,
Total: total,
}, nil
}
//获取deployment详情
func (d *deployment) GetDeploymentDetail(deploymentName, namespace string) (deployment *appsv1.Deployment, err error) {
deployment, err = K8s.ClientSet.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
if err != nil {
logger.Error(errors.New("获取Deployment详情失败, " + err.Error()))
return nil, errors.New("获取Deployment详情失败, " + err.Error())
}
return deployment, nil
}
//设置deployment副本数
func (d *deployment) ScaleDeployment(deploymentName, namespace string, scaleNum int) (replica int32, err error) {
scale, err := K8s.ClientSet.AppsV1().Deployments(namespace).GetScale(context.TODO(), deploymentName, metav1.GetOptions{})
if err != nil {
logger.Error(errors.New("获取Deployment副本数信息失败, " + err.Error()))
return 0, errors.New("获取Deployment副本数信息失败, " + err.Error())
}
scale.Spec.Replicas = int32(scaleNum)
newScale, err := K8s.ClientSet.AppsV1().Deployments(namespace).UpdateScale(context.TODO(), deploymentName, scale, metav1.UpdateOptions{})
if err != nil {
logger.Error(errors.New("更新Deployment副本数信息失败, " + err.Error()))
return 0, errors.New("更新Deployment副本数信息失败, " + err.Error())
}
return newScale.Spec.Replicas, nil
}
//创建deployment接收DeployCreate对象
func (d *deployment) CreateDeployment(data *DeployCreate) (err error) {
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: data.Name,
Namespace: data.Namespace,
Labels: data.Label,
},
Spec: appsv1.DeploymentSpec{
Replicas: &data.Replicas,
Selector: &metav1.LabelSelector{
MatchLabels: data.Label,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: data.Name,
Labels: data.Label,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: data.Name,
Image: data.Image,
Ports: []corev1.ContainerPort{
{
Name: "http",
Protocol: corev1.ProtocolTCP,
ContainerPort: data.ContainerPort,
},
},
},
},
},
},
},
Status: appsv1.DeploymentStatus{},
}
//判断健康检查功能是否打开,若打开,则增加健康检查功能
if data.HealthCheck {
deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: data.HealthPath,
Port: intstr.IntOrString{
Type: 0,
IntVal: data.ContainerPort,
},
},
},
InitialDelaySeconds: 5,
TimeoutSeconds: 5,
PeriodSeconds: 5,
}
deployment.Spec.Template.Spec.Containers[0].LivenessProbe = &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: data.HealthPath,
Port: intstr.IntOrString{
Type: 0,
IntVal: data.ContainerPort,
},
},
},
InitialDelaySeconds: 15,
TimeoutSeconds: 5,
PeriodSeconds: 5,
}
}
//定义容器的limit和request资源
deployment.Spec.Template.Spec.Containers[0].Resources.Limits = map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: resource.MustParse(data.Cpu),
corev1.ResourceMemory: resource.MustParse(data.Memory),
}
deployment.Spec.Template.Spec.Containers[0].Resources.Requests = map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: resource.MustParse(data.Cpu),
corev1.ResourceMemory: resource.MustParse(data.Memory),
}
_, err = K8s.ClientSet.AppsV1().Deployments(data.Namespace).
Create(context.TODO(), deployment, metav1.CreateOptions{})
if err != nil {
logger.Error(errors.New("创建Deployment失败, " + err.Error()))
return errors.New("创建Deployment失败, " + err.Error())
}
return nil
}
//删除deployment
func (d *deployment) DeleteDeployment(deploymentName, namespace string) (err error) {
err = K8s.ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), deploymentName, metav1.DeleteOptions{})
if err != nil {
logger.Error(errors.New("删除Deployment失败, " + err.Error()))
return errors.New("删除Deployment失败, " + err.Error())
}
return nil
}
//重启deployment
func (d *deployment) RestartDeployment(deploymentName, namespace string) (err error) {
patchData := map[string]interface{}{
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []map[string]interface{}{
{"name": deploymentName,
"env": []map[string]string{{
"name": "RESTART_",
"value": strconv.FormatInt(time.Now().Unix(), 10),
}},
},
},
},
},
},
}
patchByte, err := json.Marshal(patchData)
if err != nil {
logger.Error(errors.New("json序列化失败, " + err.Error()))
return errors.New("json序列化失败, " + err.Error())
}
_, err = K8s.ClientSet.AppsV1().Deployments(namespace).Patch(context.TODO(), deploymentName, "application/strategic-merge-patch+json", patchByte, metav1.PatchOptions{})
if err != nil {
logger.Error(errors.New("重启Deployment失败, " + err.Error()))
return errors.New("重启Deployment失败, " + err.Error())
}
return nil
}
//更新deployment
func (d *deployment) UpdateDeployment(namespace, content string) (err error) {
var deploy = &appsv1.Deployment{}
err = json.Unmarshal([]byte(content), deploy)
if err != nil {
logger.Error(errors.New("反序列化失败, " + err.Error()))
return errors.New("反序列化失败, " + err.Error())
}
_, err = K8s.ClientSet.AppsV1().Deployments(namespace).Update(context.TODO(), deploy, metav1.UpdateOptions{})
if err != nil {
logger.Error(errors.New("更新Deployment失败, " + err.Error()))
return errors.New("更新Deployment失败, " + err.Error())
}
return nil
}
//获取每个namespace的deployment数量
func (d *deployment) GetDeployNumPerNp() (deploysNps []*DeploysNp, err error) {
namespaceList, err := K8s.ClientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
for _, namespace := range namespaceList.Items {
deploymentList, err := K8s.ClientSet.AppsV1().Deployments(namespace.Name).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
deploysNp := &DeploysNp{
Namespace: namespace.Name,
DeployNum: len(deploymentList.Items),
}
deploysNps = append(deploysNps, deploysNp)
}
return deploysNps, nil
}
//类型转换
func (d *deployment) toCells(deployments []appsv1.Deployment) []DataCell {
cells := make([]DataCell, len(deployments))
for i := range deployments {
cells[i] = deploymentCell(deployments[i])
}
return cells
}
func (d *deployment) fromCells(cells []DataCell) []appsv1.Deployment {
deployments := make([]appsv1.Deployment, len(cells))
for i := range cells {
//cells[i].(podCell)是将DataCell类型转成podCell
deployments[i] = appsv1.Deployment(cells[i].(deploymentCell))
}
return deployments
}