37 Star 396 Fork 71

GVPrancher / rancher

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
deploy.go 26.78 KB
一键复制 编辑 原始数据 按行查看 历史
Dan Ramich 提交于 2019-06-12 13:38 . goimport linting changes
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
package pipelineexecution
import (
"crypto/rsa"
"crypto/x509"
"encoding/json"
"fmt"
"math/rand"
"strconv"
"time"
"github.com/pkg/errors"
"github.com/rancher/rancher/pkg/controllers/user/nslabels"
"github.com/rancher/rancher/pkg/controllers/user/resourcequota"
images "github.com/rancher/rancher/pkg/image"
namespaceutil "github.com/rancher/rancher/pkg/namespace"
"github.com/rancher/rancher/pkg/pipeline/utils"
"github.com/rancher/rancher/pkg/randomtoken"
"github.com/rancher/rancher/pkg/ref"
"github.com/rancher/rke/pki"
mv3 "github.com/rancher/types/apis/management.cattle.io/v3"
"github.com/sirupsen/logrus"
appsv1beta2 "k8s.io/api/apps/v1beta2"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/net"
"k8s.io/client-go/util/cert"
"k8s.io/kubernetes/pkg/credentialprovider"
)
const projectIDFieldLabel = "field.cattle.io/projectId"
const defaultPortRange = "34000-35000"
func (l *Lifecycle) deploy(projectName string) error {
clusterID, projectID := ref.Parse(projectName)
ns := getPipelineNamespace(clusterID, projectID)
if _, err := l.namespaceLister.Get("", ns.Name); err == nil {
return l.reconcileRb(projectName)
} else if !apierrors.IsNotFound(err) {
return err
}
logrus.Debug("deploy pipeline workloads and services")
if _, err := l.namespaces.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the pipeline namespace")
}
if err := l.waitResourceQuotaInitCondition(ns.Name); err != nil {
return err
}
token, err := randomtoken.Generate()
if err != nil {
logrus.Warningf("warning generate random token got - %v, use default instead", err)
token = utils.PipelineSecretDefaultToken
}
nsName := utils.GetPipelineCommonName(projectName)
ns = getCommonPipelineNamespace()
if _, err := l.namespaces.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the cattle-pipeline namespace")
}
secret := getPipelineSecret(nsName, token)
for i := 0; i < 3; i++ {
// If project resource quota is enabled, It won't succeed until the resource quota in namespace is synced.
// Do retries for this case.
if _, err = l.secrets.Create(secret); err == nil || apierrors.IsAlreadyExists(err) {
break
}
time.Sleep(2 * time.Second)
}
if err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating a pipeline secret")
}
apikey, err := l.systemAccountManager.GetOrCreateProjectSystemToken(projectID)
if err != nil {
return err
}
secret = GetAPIKeySecret(nsName, apikey)
if _, err := l.secrets.Create(secret); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating a pipeline secret")
}
if err := l.reconcileRegistryCASecret(clusterID); err != nil {
return err
}
if err := l.reconcileRegistryCrtSecret(clusterID, projectID); err != nil {
return err
}
sa := getServiceAccount(nsName)
if _, err := l.serviceAccounts.Create(sa); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating a pipeline service account")
}
np := getNetworkPolicy(nsName)
if _, err := l.networkPolicies.Create(np); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error create a pipeline networkpolicy")
}
jenkinsService := getJenkinsService(nsName)
if _, err := l.services.Create(jenkinsService); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the jenkins service")
}
jenkinsDeployment := GetJenkinsDeployment(nsName)
if _, err := l.deployments.Create(jenkinsDeployment); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the jenkins deployment")
}
registryService := getRegistryService(nsName)
if _, err := l.services.Create(registryService); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the registry service")
}
registryDeployment := GetRegistryDeployment(nsName)
if _, err := l.deployments.Create(registryDeployment); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the registry deployment")
}
minioService := getMinioService(nsName)
if _, err := l.services.Create(minioService); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the minio service")
}
minioDeployment := GetMinioDeployment(nsName)
if _, err := l.deployments.Create(minioDeployment); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the minio deployment")
}
if err := l.reconcileProxyConfigMap(projectID); err != nil {
return err
}
//docker credential for local registry
if err := l.reconcileRegistryCredential(projectName, token); err != nil {
return err
}
nginxDaemonset := getProxyDaemonset()
if _, err := l.daemonsets.Create(nginxDaemonset); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error creating the nginx proxy")
}
return l.reconcileRb(projectName)
}
func (l *Lifecycle) waitResourceQuotaInitCondition(namespace string) error {
tries := 0
for tries <= 3 {
ns, err := l.namespaces.Get(namespace, metav1.GetOptions{})
if err != nil {
return err
}
invalid, err := namespaceutil.IsNamespaceConditionSet(ns, resourcequota.ResourceQuotaValidatedCondition, false)
if err != nil {
return err
}
if invalid {
return fmt.Errorf("available resource quota in this project does not fit for the dedicated pipeline namespace, please make sure there is vacancy for the default namespace quota")
}
set, err := namespaceutil.IsNamespaceConditionSet(ns, resourcequota.ResourceQuotaInitCondition, true)
if err != nil {
return err
}
if set {
break
}
time.Sleep(2 * time.Second)
tries++
}
return nil
}
func getCommonPipelineNamespace() *corev1.Namespace {
return &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: utils.PipelineNamespace,
},
}
}
func getPipelineNamespace(clusterID, projectID string) *corev1.Namespace {
ns := projectID + utils.PipelineNamespaceSuffix
return &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: ns,
Labels: labels.Set(map[string]string{
nslabels.ProjectIDFieldLabel: projectID,
utils.PipelineNamespaceLabel: "true",
}),
Annotations: map[string]string{nslabels.ProjectIDFieldLabel: ref.FromStrings(clusterID, projectID)},
},
}
}
func getPipelineSecret(ns string, token string) *corev1.Secret {
hashed, err := utils.BCryptHash(token)
if err != nil {
logrus.Warningf("warning hash registry token got - %v", err)
}
registryToken := fmt.Sprintf("%s:%s", utils.PipelineSecretDefaultUser, hashed)
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.PipelineSecretName,
},
Data: map[string][]byte{
utils.PipelineSecretTokenKey: []byte(token),
utils.PipelineSecretUserKey: []byte(utils.PipelineSecretDefaultUser),
utils.PipelineSecretRegistryTokenKey: []byte(registryToken),
},
}
}
func GetAPIKeySecret(ns string, key string) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.PipelineAPIKeySecretName,
},
Data: map[string][]byte{
utils.PipelineSecretAPITokenKey: []byte(key),
},
}
}
func (l *Lifecycle) reconcileRegistryCASecret(clusterID string) error {
cn := "docker-registry-ca"
CACrt, CAKey, err := pki.GenerateCACertAndKey(cn, nil)
if err != nil {
return err
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: clusterID,
Name: utils.RegistryCACrtSecretName,
},
Data: map[string][]byte{
utils.RegistryCACrt: cert.EncodeCertPEM(CACrt),
utils.RegistryCAKey: cert.EncodePrivateKeyPEM(CAKey),
},
}
if _, err := l.managementSecrets.Create(secret); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error create registry ca secret")
}
return nil
}
func (l *Lifecycle) reconcileRegistryCrtSecret(clusterID, projectID string) error {
ns := projectID + utils.PipelineNamespaceSuffix
// generate domain cert & key if they do not exist
_, err := l.secrets.GetNamespaced(ns, utils.RegistryCrtSecretName, metav1.GetOptions{})
if err == nil || !apierrors.IsNotFound(err) {
return err
}
// ca cert for proxy
caSecret, err := l.managementSecrets.GetNamespaced(clusterID, utils.RegistryCACrtSecretName, metav1.GetOptions{})
if err != nil {
return err
}
crtRaw := caSecret.Data[utils.RegistryCACrt]
keyRaw := caSecret.Data[utils.RegistryCAKey]
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: utils.PipelineNamespace,
Name: utils.RegistryCACrtSecretName,
},
Data: map[string][]byte{
utils.RegistryCACrt: crtRaw,
},
}
if _, err := l.secrets.Create(secret); err != nil && !apierrors.IsAlreadyExists(err) {
return err
}
caCrt, err := cert.ParseCertsPEM(crtRaw)
if err != nil || len(caCrt) < 1 {
return errors.Wrap(err, "invalid pem format")
}
caKey, err := cert.ParsePrivateKeyPEM(keyRaw)
if _, ok := caKey.(*rsa.PrivateKey); !ok || err != nil {
return errors.Wrap(err, "invalid pem format")
}
cfg := cert.Config{
CommonName: utils.RegistryName,
Organization: []string{},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
AltNames: cert.AltNames{
DNSNames: []string{
utils.RegistryName,
fmt.Sprintf("%s.%s", utils.RegistryName, ns),
fmt.Sprintf("%s.%s.svc.cluster.local", utils.RegistryName, ns),
},
},
}
key, err := cert.NewPrivateKey()
if err != nil {
return err
}
duration := getSigningDuration(l.pipelineSettingLister, projectID)
crt, err := newSignedCertWithDuration(cfg, duration, key, caCrt[0], caKey.(*rsa.PrivateKey))
if err != nil {
return err
}
secret = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.RegistryCrtSecretName,
},
Data: map[string][]byte{
utils.RegistryCrt: cert.EncodeCertPEM(crt),
utils.RegistryKey: cert.EncodePrivateKeyPEM(key),
utils.RegistryCACrt: crtRaw,
},
}
if _, err := l.secrets.Create(secret); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error create secret")
}
return nil
}
func getRegistryCredential(projectID string, token string, hostname string) (*corev1.Secret, error) {
_, ns := ref.Parse(projectID)
config := credentialprovider.DockerConfigJson{
Auths: credentialprovider.DockerConfig{
hostname: credentialprovider.DockerConfigEntry{
Username: utils.PipelineSecretDefaultUser,
Password: token,
Email: "",
},
},
}
configJSON, err := json.Marshal(config)
if err != nil {
return nil, err
}
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: utils.DockerCredentialName,
Namespace: ns,
Annotations: map[string]string{
projectIDFieldLabel: projectID,
},
},
Data: map[string][]byte{
corev1.DockerConfigJsonKey: configJSON,
},
Type: corev1.SecretTypeDockerConfigJson,
}, nil
}
func getServiceAccount(ns string) *corev1.ServiceAccount {
return &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.JenkinsName,
},
}
}
func getRoleBindings(rbNs string, commonName string) *rbacv1.RoleBinding {
return &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: commonName,
Namespace: rbNs,
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: roleAdmin,
},
Subjects: []rbacv1.Subject{{
Kind: rbacv1.ServiceAccountKind,
Namespace: commonName,
Name: utils.JenkinsName,
}},
}
}
func getClusterRoleBindings(ns string, roleName string) *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: ns + "-" + roleName,
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: roleName,
},
Subjects: []rbacv1.Subject{{
Kind: rbacv1.ServiceAccountKind,
Namespace: ns,
Name: utils.JenkinsName,
}},
}
}
func getJenkinsService(ns string) *corev1.Service {
return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.JenkinsName,
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
utils.LabelKeyApp: utils.JenkinsName,
utils.LabelKeyJenkins: utils.JenkinsMaster,
},
Ports: []corev1.ServicePort{
{
Name: "http",
Port: utils.JenkinsPort,
},
{
Name: "agent",
Port: utils.JenkinsJNLPPort,
},
},
},
}
}
func GetJenkinsDeployment(ns string) *appsv1beta2.Deployment {
replicas := int32(1)
return &appsv1beta2.Deployment{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.JenkinsName,
},
Spec: appsv1beta2.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{utils.LabelKeyApp: utils.JenkinsName},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
utils.LabelKeyApp: utils.JenkinsName,
utils.LabelKeyJenkins: utils.JenkinsMaster,
},
Name: utils.JenkinsName,
},
Spec: corev1.PodSpec{
ServiceAccountName: utils.JenkinsName,
Containers: []corev1.Container{
{
Name: utils.JenkinsName,
Image: images.Resolve(mv3.ToolsSystemImages.PipelineSystemImages.Jenkins),
Env: []corev1.EnvVar{
{
Name: "ADMIN_PASSWORD",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: utils.PipelineSecretName,
},
Key: utils.PipelineSecretTokenKey,
}},
}, {
Name: "ADMIN_USER",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: utils.PipelineSecretName,
},
Key: utils.PipelineSecretUserKey,
}},
}, {
Name: "JAVA_OPTS",
Value: "-Xmx300m -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Dhudson.model.LoadStatistics.clock=2000 -Dhudson.slaves.NodeProvisioner.recurrencePeriod=2000",
}, {
Name: "NAMESPACE",
Value: ns,
}, {
Name: "JENKINS_POD_IP",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "status.podIP",
},
},
},
},
Ports: []corev1.ContainerPort{
{
Name: "http",
ContainerPort: utils.JenkinsPort,
},
{
Name: "agent",
ContainerPort: utils.JenkinsJNLPPort,
},
},
ReadinessProbe: &corev1.Probe{
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/login",
Port: intstr.FromInt(utils.JenkinsPort),
},
},
},
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024E6, resource.BinarySI),
},
Requests: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(300E6, resource.BinarySI),
},
},
},
},
},
},
},
}
}
func getNetworkPolicy(ns string) *v1.NetworkPolicy {
return &v1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.NetWorkPolicyName,
},
Spec: v1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: utils.LabelKeyApp,
Operator: metav1.LabelSelectorOpIn,
Values: []string{utils.JenkinsName, utils.MinioName},
},
},
},
Ingress: []v1.NetworkPolicyIngressRule{{}},
},
}
}
func getRegistryService(ns string) *corev1.Service {
return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.RegistryName,
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
utils.LabelKeyApp: utils.RegistryName,
},
Ports: []corev1.ServicePort{
{
Name: utils.RegistryName,
Port: utils.RegistryPort,
},
},
},
}
}
func GetRegistryDeployment(ns string) *appsv1beta2.Deployment {
replicas := int32(1)
return &appsv1beta2.Deployment{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.RegistryName,
},
Spec: appsv1beta2.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{utils.LabelKeyApp: utils.RegistryName},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{utils.LabelKeyApp: utils.RegistryName},
Name: utils.RegistryName,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: utils.RegistryName,
Image: images.Resolve(mv3.ToolsSystemImages.PipelineSystemImages.Registry),
ImagePullPolicy: corev1.PullAlways,
Ports: []corev1.ContainerPort{
{
Name: utils.RegistryName,
ContainerPort: utils.RegistryPort,
},
},
Env: []corev1.EnvVar{
{
Name: "REGISTRY_HTTP_ADDR",
Value: "0.0.0.0:443",
},
{
Name: "REGISTRY_HTTP_TLS_CERTIFICATE",
Value: utils.RegistryCrtPath + utils.RegistryCrt,
},
{
Name: "REGISTRY_HTTP_TLS_KEY",
Value: utils.RegistryCrtPath + utils.RegistryKey,
},
{
Name: "REGISTRY_AUTH",
Value: "htpasswd",
},
{
Name: "REGISTRY_AUTH_HTPASSWD_REALM",
Value: "Registry Realm",
},
{
Name: "REGISTRY_AUTH_HTPASSWD_PATH",
Value: utils.RegistryAuthPath + utils.PipelineSecretRegistryTokenKey,
},
},
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(200E6, resource.BinarySI),
},
Requests: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI),
},
},
VolumeMounts: []corev1.VolumeMount{
{
Name: utils.RegistryCrtVolumeName,
MountPath: utils.RegistryCrtPath,
ReadOnly: true,
},
{
Name: utils.RegistryAuthVolumeName,
MountPath: utils.RegistryAuthPath,
ReadOnly: true,
},
},
},
},
Volumes: []corev1.Volume{
{
Name: utils.RegistryCrtVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: utils.RegistryCrtSecretName,
},
},
},
{
Name: utils.RegistryAuthVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: utils.PipelineSecretName,
Items: []corev1.KeyToPath{
{
Key: utils.PipelineSecretRegistryTokenKey,
Path: utils.PipelineSecretRegistryTokenKey,
},
},
},
},
},
},
},
},
},
}
}
func (l *Lifecycle) reconcileProxyConfigMap(projectID string) error {
exist := true
cm, err := l.configMapLister.Get(utils.PipelineNamespace, utils.ProxyConfigMapName)
if apierrors.IsNotFound(err) {
exist = false
} else if err != nil {
return err
}
if !exist {
port, err := l.getAvailablePort()
if err != nil {
return err
}
toCreate := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: utils.PipelineNamespace,
Name: utils.ProxyConfigMapName,
},
Data: map[string]string{},
}
if err := utils.SetRegistryPortMapping(toCreate, map[string]string{projectID: port}); err != nil {
return err
}
_, err = l.configMaps.Create(toCreate)
return err
}
portMap, err := utils.GetRegistryPortMapping(cm)
if err != nil {
return err
}
if _, ok := portMap[projectID]; !ok {
port, err := l.getAvailablePort()
if err != nil {
return err
}
toUpdate := cm.DeepCopy()
portMap, err = utils.GetRegistryPortMapping(toUpdate)
if err != nil {
return err
}
portMap[projectID] = port
if err := utils.SetRegistryPortMapping(toUpdate, portMap); err != nil {
return err
}
_, err = l.configMaps.Update(toUpdate)
return err
}
return nil
}
func (l *Lifecycle) getAvailablePort() (string, error) {
portRange := &net.PortRange{}
portRange.Set(defaultPortRange)
rand.Seed(time.Now().UnixNano())
rd := rand.Intn(portRange.Size)
portMap := map[string]string{}
cm, err := l.configMapLister.Get(utils.PipelineNamespace, utils.ProxyConfigMapName)
if apierrors.IsNotFound(err) {
return strconv.Itoa(rd + portRange.Base), nil
} else if err != nil {
return "", err
}
portMap, err = utils.GetRegistryPortMapping(cm)
if err != nil {
return "", err
}
usedPorts := map[string]bool{}
for _, p := range portMap {
usedPorts[p] = true
}
for i := 0; i < portRange.Size; i++ {
port := strconv.Itoa((rd+i)%portRange.Size + portRange.Base)
if !usedPorts[port] {
return port, nil
}
}
return "", errors.New("No available port")
}
func getProxyDaemonset() *appsv1beta2.DaemonSet {
return &appsv1beta2.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: utils.PipelineNamespace,
Name: utils.RegistryProxyName,
},
Spec: appsv1beta2.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{utils.LabelKeyApp: utils.RegistryProxyName},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{utils.LabelKeyApp: utils.RegistryProxyName},
Name: utils.RegistryProxyName,
},
Spec: corev1.PodSpec{
HostNetwork: true,
DNSPolicy: corev1.DNSClusterFirstWithHostNet,
Containers: []corev1.Container{
{
Name: utils.RegistryProxyName,
Image: images.Resolve(mv3.ToolsSystemImages.PipelineSystemImages.RegistryProxy),
Command: []string{"nginx-proxy"},
VolumeMounts: []corev1.VolumeMount{
{
Name: utils.RegistryPortMappingKey,
MountPath: utils.RegistryMappingPath,
},
{
Name: utils.RegistryCrtVolumeName,
MountPath: utils.RegistryCrtPath,
},
},
},
},
Volumes: []corev1.Volume{
{
Name: utils.RegistryPortMappingKey,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{Name: utils.ProxyConfigMapName},
Items: []corev1.KeyToPath{
{Key: utils.RegistryPortMappingFile,
Path: utils.RegistryPortMappingFile,
},
},
},
},
},
{
Name: utils.RegistryCrtVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: utils.RegistryCACrtSecretName,
},
},
},
},
},
},
},
}
}
func getMinioService(ns string) *corev1.Service {
return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.MinioName,
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
utils.LabelKeyApp: utils.MinioName,
},
Ports: []corev1.ServicePort{
{
Name: utils.MinioName,
Port: utils.MinioPort,
},
},
},
}
}
func GetMinioDeployment(ns string) *appsv1beta2.Deployment {
replicas := int32(1)
return &appsv1beta2.Deployment{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: utils.MinioName,
},
Spec: appsv1beta2.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{utils.LabelKeyApp: utils.MinioName},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{utils.LabelKeyApp: utils.MinioName},
Name: utils.MinioName,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: utils.MinioName,
Image: images.Resolve(mv3.ToolsSystemImages.PipelineSystemImages.Minio),
ImagePullPolicy: corev1.PullAlways,
Args: []string{"server", "/data"},
Env: []corev1.EnvVar{
{
Name: "MINIO_SECRET_KEY",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: utils.PipelineSecretName,
},
Key: utils.PipelineSecretTokenKey,
}},
}, {
Name: "MINIO_ACCESS_KEY",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: utils.PipelineSecretName,
},
Key: utils.PipelineSecretUserKey,
}},
},
},
Ports: []corev1.ContainerPort{
{
Name: utils.MinioName,
ContainerPort: utils.MinioPort,
},
},
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(200E6, resource.BinarySI),
},
Requests: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI),
},
},
},
},
},
},
},
}
}
func (l *Lifecycle) reconcileRegistryCredential(projectName, token string) error {
cm, err := l.configMaps.GetNamespaced(utils.PipelineNamespace, utils.ProxyConfigMapName, metav1.GetOptions{})
if err != nil {
return err
}
portMap, err := utils.GetRegistryPortMapping(cm)
if err != nil {
return err
}
_, projectID := ref.Parse(projectName)
port, ok := portMap[projectID]
if !ok || port == "" {
return errors.New("Found no port for local registry")
}
regHostname := "127.0.0.1:" + port
dockerCredential, err := getRegistryCredential(projectName, token, regHostname)
if err != nil {
return err
}
if _, err := l.managementSecrets.Create(dockerCredential); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "Error create credential for local registry")
}
return nil
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/rancher/rancher.git
git@gitee.com:rancher/rancher.git
rancher
rancher
rancher
v2.2.7-rc6

搜索帮助

344bd9b3 5694891 D2dac590 5694891