Ejemplo n.º 1
0
    public AksStack()
    {
        var resourceGroup = new ResourceGroup("aks-rg");

        var randomPassword = new RandomPassword("password", new RandomPasswordArgs
        {
            Length  = 20,
            Special = true,
        }).Result;

        var sshPublicKey = new PrivateKey("ssh-key", new PrivateKeyArgs
        {
            Algorithm = "RSA",
            RsaBits   = 4096,
        }).PublicKeyOpenssh;

        // Create the AD service principal for the K8s cluster.
        var adApp = new Application("aks");
        var adSp  = new ServicePrincipal("aksSp", new ServicePrincipalArgs {
            ApplicationId = adApp.ApplicationId
        });
        var adSpPassword = new ServicePrincipalPassword("aksSpPassword", new ServicePrincipalPasswordArgs
        {
            ServicePrincipalId = adSp.Id,
            Value   = randomPassword,
            EndDate = "2099-01-01T00:00:00Z",
        });

        // Grant networking permissions to the SP (needed e.g. to provision Load Balancers).
        var assignment = new Assignment("role-assignment", new AssignmentArgs
        {
            PrincipalId        = adSp.Id,
            Scope              = resourceGroup.Id,
            RoleDefinitionName = "Network Contributor"
        });

        // Create a Virtual Network for the cluster.
        var vnet = new VirtualNetwork("vnet", new VirtualNetworkArgs
        {
            ResourceGroupName = resourceGroup.Name,
            AddressSpaces     = { "10.2.0.0/16" },
        });

        // Create a Subnet for the cluster.
        var subnet = new Subnet("subnet", new SubnetArgs
        {
            ResourceGroupName  = resourceGroup.Name,
            VirtualNetworkName = vnet.Name,
            AddressPrefix      = "10.2.1.0/24",
        });

        // Now allocate an AKS cluster.
        var cluster = new KubernetesCluster("aksCluster", new KubernetesClusterArgs
        {
            ResourceGroupName = resourceGroup.Name,
            DefaultNodePool   = new KubernetesClusterDefaultNodePoolArgs
            {
                Name         = "aksagentpool",
                NodeCount    = 3,
                VmSize       = "Standard_B2s",
                OsDiskSizeGb = 30,
                VnetSubnetId = subnet.Id
            },
            DnsPrefix    = "sampleaks",
            LinuxProfile = new KubernetesClusterLinuxProfileArgs
            {
                AdminUsername = "******",
                SshKey        = new KubernetesClusterLinuxProfileSshKeyArgs
                {
                    KeyData = sshPublicKey,
                },
            },
            ServicePrincipal = new KubernetesClusterServicePrincipalArgs
            {
                ClientId     = adApp.ApplicationId,
                ClientSecret = adSpPassword.Value,
            },
            KubernetesVersion      = "1.16.9",
            RoleBasedAccessControl = new KubernetesClusterRoleBasedAccessControlArgs {
                Enabled = true
            },
            NetworkProfile = new KubernetesClusterNetworkProfileArgs
            {
                NetworkPlugin    = "azure",
                DnsServiceIp     = "10.2.2.254",
                ServiceCidr      = "10.2.2.0/24",
                DockerBridgeCidr = "172.17.0.1/16",
            },
        });

        // Create a k8s provider pointing to the kubeconfig.
        var k8sProvider = new Pulumi.Kubernetes.Provider("k8s", new Pulumi.Kubernetes.ProviderArgs
        {
            KubeConfig = cluster.KubeConfigRaw
        });

        var customResourceOptions = new CustomResourceOptions
        {
            Provider = k8sProvider
        };

        // Create a Container Registry.
        var registry = new Registry("acregistry", new RegistryArgs
        {
            ResourceGroupName = resourceGroup.Name,
            Sku          = "Basic",
            AdminEnabled = true
        });

        // Build & push the sample application to the registry.
        var applicationName = "sample-application";
        var imageName       = registry.LoginServer.Apply(value => $"{value}/{applicationName}");

        var image = new Image(applicationName, new ImageArgs
        {
            Build    = "./SampleApplication",
            Registry = new ImageRegistry
            {
                Server   = registry.LoginServer,
                Username = registry.AdminUsername,
                Password = registry.AdminPassword
            },
            ImageName = imageName
        }, new ComponentResourceOptions
        {
            Provider = k8sProvider
        });

        // Create a k8s secret for use when pulling images from the container registry when deploying the sample application.
        var dockerCfg = Output.All <string>(registry.LoginServer, registry.AdminUsername, registry.AdminPassword).Apply(
            values =>
        {
            var r        = new Dictionary <string, object>();
            var server   = values[0];
            var username = values[1];
            var password = values[2];

            r[server] = new
            {
                email = "*****@*****.**",
                username,
                password
            };

            return(r);
        });

        var dockerCfgString = dockerCfg.Apply(x =>
                                              Convert.ToBase64String(Encoding.UTF8.GetBytes(System.Text.Json.JsonSerializer.Serialize(x))));

        var dockerCfgSecretName = "dockercfg-secret";

        var dockerCfgSecret = new Pulumi.Kubernetes.Core.V1.Secret(dockerCfgSecretName, new SecretArgs
        {
            Data =
            {
                { ".dockercfg", dockerCfgString }
            },
            Type     = "kubernetes.io/dockercfg",
            Metadata = new ObjectMetaArgs
            {
                Name = dockerCfgSecretName,
            }
        }, customResourceOptions);

        // Deploy the sample application to the cluster.
        var labels = new InputMap <string>
        {
            { "app", $"app-{applicationName}" },
        };

        var deployment = new Pulumi.Kubernetes.Apps.V1.Deployment(applicationName, new DeploymentArgs
        {
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = labels,
                },
                Replicas = 1,
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = labels,
                        Name   = applicationName
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers = new List <ContainerArgs>
                        {
                            new ContainerArgs
                            {
                                Name  = applicationName,
                                Image = image.ImageName,
                            }
                        },
                        ImagePullSecrets = new LocalObjectReferenceArgs
                        {
                            Name = dockerCfgSecretName
                        }
                    }
                }
            }
        }, customResourceOptions);

        // Create a new service.
        var service = new Pulumi.Kubernetes.Core.V1.Service(applicationName, new ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Name   = applicationName,
                Labels = labels
            },
            Spec = new ServiceSpecArgs
            {
                Type     = "LoadBalancer",
                Selector = deployment.Spec.Apply(x => x.Template.Metadata.Labels),
                Ports    = new ServicePortArgs
                {
                    Port = 80
                }
            }
        }, customResourceOptions);

        this.KubeConfig          = cluster.KubeConfigRaw;
        this.DockercfgSecretName = dockerCfgSecret.Metadata.Apply(x => x.Name);
    }
Ejemplo n.º 2
0
    static Task <int> Main(string[] args)
    {
        return(Pulumi.Deployment.RunAsync(() =>
        {
            var config = new Pulumi.Config();
            var pw = config.RequireSecret("message");
            var rawPw = config.Require("message");

            var cmData = new CoreV1.ConfigMap("cmdata", new ConfigMapArgs
            {
                Data = new InputMap <string>
                {
                    { "password", pw },
                }
            });

            var cmBinaryData = new CoreV1.ConfigMap("cmbinarydata", new ConfigMapArgs
            {
                BinaryData = new InputMap <string>
                {
                    { "password", pw.Apply(v => Base64Encode(v)) },
                }
            });

            var sStringData = new CoreV1.Secret("sstringdata", new SecretArgs
            {
                StringData = new InputMap <string>
                {
                    { "password", rawPw }
                }
            });

            var sData = new CoreV1.Secret("sdata", new SecretArgs
            {
                Data = new InputMap <string>
                {
                    { "password", Base64Encode(rawPw) }
                }
            });

            var name = $"test-{RandomString()}";
            var secretYAML = $@"
apiVersion: v1
kind: Secret
metadata:
  name: {name}
stringData:
  password: {rawPw}
";
            var cg = new Yaml.ConfigGroup("example", new Yaml.ConfigGroupArgs
            {
                Yaml = secretYAML
            });
            var cgSecret = cg.GetResource <CoreV1.Secret>(name);

            return new Dictionary <string, object>
            {
                { "cmData", cmData.Data },
                { "cmBinaryData", cmData.BinaryData },
                { "sStringData", sStringData.StringData },
                { "sData", sStringData.Data },
                { "cgData", cgSecret.Apply(v => v.Data) },
            };
        }));
    }
        private static void SetupAppointmentApiInKubernetes(AzureResourceBag azureResources, AppointmentApiAzureResourceBag appointmentApiAzureResources, PetDoctorClusterOptions clusterOptions)
        {
            var customOpts = new CustomResourceOptions
            {
                DependsOn = azureResources.Cluster,
                Provider  = azureResources.ClusterProvider
            };

            var secret = new Secret(clusterOptions.AppointmentApi.SecretName, new SecretArgs
            {
                Metadata = new ObjectMetaArgs
                {
                    Namespace = clusterOptions.Namespace,
                    Name      = clusterOptions.AppointmentApi.SecretName
                },
                Kind       = "Secret",
                ApiVersion = "v1",
                Type       = "Opaque",
                Data       = new InputMap <string>
                {
                    { "keyvault-url", appointmentApiAzureResources.KeyVault.VaultUri.Apply(kvUrl => Convert.ToBase64String(Encoding.UTF8.GetBytes(kvUrl))) },
                    { "appinsights-instrumentationkey", azureResources.AppInsights.InstrumentationKey.Apply(key => Convert.ToBase64String(Encoding.UTF8.GetBytes(key))) }
                }
            }, customOpts);

            var appointmentApiPodIdentity = new CustomResource(clusterOptions.AppointmentApi.AadPodIdentityName,
                                                               new AzureIdentityResourceArgs
            {
                Metadata = new ObjectMetaArgs
                {
                    Name = clusterOptions.AppointmentApi.AadPodIdentityName
                },
                Spec = new AzureIdentitySpecArgs
                {
                    Type       = 0,
                    ResourceId = appointmentApiAzureResources.Identity.Id,
                    ClientId   = appointmentApiAzureResources.Identity.ClientId
                }
            }, customOpts);

            var appointmentApiPodIdentityBinding = new CustomResource(clusterOptions.AppointmentApi.AadPodIdentityBindingName,
                                                                      new AzureIdentityBindingResourceArgs
            {
                Metadata = new ObjectMetaArgs
                {
                    Name = clusterOptions.AppointmentApi.AadPodIdentityBindingName
                },
                Spec = new AzureIdentityBindingSpecArgs
                {
                    AzureIdentity = clusterOptions.AppointmentApi.AadPodIdentityName,
                    Selector      = clusterOptions.AppointmentApi.AadPodIdentitySelector
                }
            }, new CustomResourceOptions
            {
                DependsOn = new InputList <Resource> {
                    azureResources.Cluster, appointmentApiAzureResources.Identity
                },
                Provider = azureResources.ClusterProvider
            });

            var appointmentApiDeployment = new Deployment("appointment-api-deployment", new DeploymentArgs
            {
                ApiVersion = "apps/v1beta1",
                Kind       = "Deployment",
                Metadata   = new ObjectMetaArgs
                {
                    Name      = clusterOptions.AppointmentApi.DeploymentName,
                    Namespace = clusterOptions.Namespace,
                    Labels    = new InputMap <string>
                    {
                        { "app", clusterOptions.AppointmentApi.DeploymentName },
                        { "aadpodidbinding", clusterOptions.AppointmentApi.AadPodIdentitySelector }
                    }
                },
                Spec = new DeploymentSpecArgs
                {
                    Replicas = clusterOptions.AppointmentApi.ReplicaCount,
                    Selector = new LabelSelectorArgs
                    {
                        MatchLabels = new InputMap <string>
                        {
                            { "app", clusterOptions.AppointmentApi.DeploymentName }
                        }
                    },
                    Template = new PodTemplateSpecArgs
                    {
                        Metadata = new ObjectMetaArgs
                        {
                            Labels = new InputMap <string>
                            {
                                { "app", clusterOptions.AppointmentApi.DeploymentName },
                                { "aadpodidbinding", clusterOptions.AppointmentApi.AadPodIdentitySelector }
                            }
                        },
                        Spec = new PodSpecArgs
                        {
                            Containers = new InputList <ContainerArgs>
                            {
                                new ContainerArgs
                                {
                                    Name  = clusterOptions.AppointmentApi.DeploymentName,
                                    Image = clusterOptions.AppointmentApi.Image,
                                    Ports = new InputList <ContainerPortArgs>
                                    {
                                        new ContainerPortArgs
                                        {
                                            ContainerPortValue = clusterOptions.AppointmentApi.Port,
                                            Protocol           = "TCP"
                                        }
                                    },
                                    ReadinessProbe = new ProbeArgs
                                    {
                                        HttpGet = new HTTPGetActionArgs
                                        {
                                            Port   = clusterOptions.AppointmentApi.Port,
                                            Path   = "/ready",
                                            Scheme = "HTTP"
                                        },
                                        InitialDelaySeconds = 15,
                                        TimeoutSeconds      = 2,
                                        PeriodSeconds       = 10,
                                        FailureThreshold    = 3
                                    },
                                    LivenessProbe = new ProbeArgs
                                    {
                                        HttpGet = new HTTPGetActionArgs
                                        {
                                            Port   = clusterOptions.AppointmentApi.Port,
                                            Path   = "/live",
                                            Scheme = "HTTP"
                                        },
                                        InitialDelaySeconds = 30,
                                        TimeoutSeconds      = 2,
                                        PeriodSeconds       = 5,
                                        FailureThreshold    = 3
                                    },
                                    Env = new InputList <EnvVarArgs>
                                    {
                                        new EnvVarArgs
                                        {
                                            Name  = "ASPNETCORE_ENVIRONMENT",
                                            Value = "Production"
                                        },
                                        new EnvVarArgs
                                        {
                                            Name      = "KEYVAULT__URL",
                                            ValueFrom = new EnvVarSourceArgs
                                            {
                                                SecretKeyRef = new SecretKeySelectorArgs
                                                {
                                                    Name = clusterOptions.AppointmentApi.SecretName,
                                                    Key  = "keyvault-url"
                                                }
                                            }
                                        },
                                        new EnvVarArgs
                                        {
                                            Name      = "APPLICATIONINSIGHTS__INSTRUMENTATIONKEY",
                                            ValueFrom = new EnvVarSourceArgs
                                            {
                                                SecretKeyRef = new SecretKeySelectorArgs
                                                {
                                                    Name = clusterOptions.AppointmentApi.SecretName,
                                                    Key  = "appinsights-instrumentationkey"
                                                }
                                            }
                                        },
                                        new EnvVarArgs
                                        {
                                            Name  = "HOSTENV",
                                            Value = "K8S"
                                        },
                                        new EnvVarArgs
                                        {
                                            Name  = "PATH_BASE",
                                            Value = "api"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }, new CustomResourceOptions
            {
                DependsOn = new InputList <Resource> {
                    azureResources.Cluster, appointmentApiAzureResources.Identity, appointmentApiPodIdentityBinding
                },
                Provider = azureResources.ClusterProvider
            });

            var appointmentApiService = new Service(clusterOptions.AppointmentApi.ServiceName, new ServiceArgs
            {
                ApiVersion = "v1",
                Kind       = "Service",
                Metadata   = new ObjectMetaArgs
                {
                    Name      = clusterOptions.AppointmentApi.ServiceName,
                    Namespace = clusterOptions.Namespace
                },
                Spec = new ServiceSpecArgs
                {
                    Selector = new InputMap <string>
                    {
                        { "app", clusterOptions.AppointmentApi.DeploymentName }
                    },
                    Type      = "ClusterIP",
                    ClusterIP = "None",
                    Ports     = new InputList <ServicePortArgs>
                    {
                        new ServicePortArgs
                        {
                            Name       = "http",
                            Protocol   = "TCP",
                            Port       = 80,
                            TargetPort = clusterOptions.AppointmentApi.Port
                        }
                    }
                }
            }, customOpts);

            var appointmentApiIngress = new Ingress(clusterOptions.AppointmentApi.IngressName, new IngressArgs
            {
                ApiVersion = "extensions/v1beta1",
                Kind       = "Ingress",
                Metadata   = new ObjectMetaArgs
                {
                    Name        = clusterOptions.AppointmentApi.IngressName,
                    Namespace   = clusterOptions.Namespace,
                    Annotations = new InputMap <string>
                    {
                        { "kubernetes.io/ingress.class", "nginx" },
                        { "certmanager.k8s.io/cluster-issuer", "letsencrypt-prod" }
                    }
                },
                Spec = new IngressSpecArgs
                {
                    Tls = new InputList <IngressTLSArgs>
                    {
                        new IngressTLSArgs
                        {
                            Hosts = new InputList <string>
                            {
                                clusterOptions.Domain
                            },
                            SecretName = "tls-secret"
                        }
                    },
                    Rules = new InputList <IngressRuleArgs>
                    {
                        new IngressRuleArgs
                        {
                            Host = clusterOptions.Domain,
                            Http = new HTTPIngressRuleValueArgs
                            {
                                Paths = new InputList <HTTPIngressPathArgs>
                                {
                                    new HTTPIngressPathArgs
                                    {
                                        Path    = "/api",
                                        Backend = new IngressBackendArgs
                                        {
                                            ServiceName = clusterOptions.AppointmentApi.ServiceName,
                                            ServicePort = clusterOptions.AppointmentApi.Port
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }, customOpts);
        }