Ejemplo n.º 1
0
    static Task <int> Main()
    {
        return(Deployment.RunAsync(() => {
            var config = new Config();
            var nodeCount = config.GetInt32("nodeCount") ?? 2;
            var appReplicaCount = config.GetInt32("appReplicaCount") ?? 5;
            var domainName = config.Get("domainName");

            var cluster = new KubernetesCluster("do-cluser", new KubernetesClusterArgs {
                Region = "sfo2",
                Version = "latest",
                NodePool = new KubernetesClusterNodePoolArgs {
                    Name = "default",
                    Size = "s-2vcpu-2gb",
                    NodeCount = nodeCount
                }
            });

            var k8sProvider = new Provider("do-k8s", new ProviderArgs {
                KubeConfig = cluster.KubeConfigs.Apply(array => array[0].RawConfig)
            });

            var app = new Pulumi.Kubernetes.Apps.V1.Deployment("do-app-dep", new DeploymentArgs {
                Spec = new DeploymentSpecArgs {
                    Selector = new LabelSelectorArgs {
                        MatchLabels =
                        {
                            { "app", "app-nginx" }
                        }
                    },
                    Replicas = appReplicaCount,
                    Template = new PodTemplateSpecArgs {
                        Metadata = new ObjectMetaArgs {
                            Labels =
                            {
                                { "app", "app-nginx" }
                            }
                        },
                        Spec = new PodSpecArgs {
                            Containers = new ContainerArgs {
                                Name = "nginx",
                                Image = "nginx"
                            }
                        }
                    }
                }
            }, new CustomResourceOptions {
                Provider = k8sProvider
            });

            var appService = new Service("do-app-svc", new ServiceArgs {
                Spec = new ServiceSpecArgs {
                    Type = "LoadBalancer",
                    Selector = app.Spec.Apply(spec => spec.Template.Metadata.Labels),
                    Ports = new ServicePortArgs {
                        Port = 80
                    }
                }
            }, new CustomResourceOptions {
                Provider = k8sProvider
            });

            var ingressIp = appService.Status.Apply(status => status.LoadBalancer.Ingress[0].Ip);

            if (!string.IsNullOrWhiteSpace(domainName))
            {
                var domain = new Domain("do-domain", new DomainArgs {
                    Name = domainName,
                    IpAddress = ingressIp
                });

                var cnameRecord = new DnsRecord("do-domain-cname", new DnsRecordArgs {
                    Domain = domain.Name,
                    Type = "CNAME",
                    Name = "www",
                    Value = "@"
                });
            }

            return new Dictionary <string, object?> {
                { "ingressIp", ingressIp }
            };
        }));
    }
Ejemplo n.º 2
0
    public EksStack()
    {
        // Read back the default VPC and public subnets, which we will use.
        var vpc = Output.Create(Ec2.GetVpc.InvokeAsync(new Ec2.GetVpcArgs {
            Default = true
        }));
        var vpcId  = vpc.Apply(vpc => vpc.Id);
        var subnet = vpcId.Apply(id => Ec2.GetSubnetIds.InvokeAsync(new Ec2.GetSubnetIdsArgs {
            VpcId = id
        }));
        var subnetIds = subnet.Apply(s => s.Ids);

        // Create an IAM role that can be used by our service's task.
        var eksRole = new Iam.Role("eks-iam-eksRole", new Iam.RoleArgs
        {
            AssumeRolePolicy = @"{
""Version"": ""2008-10-17"",
""Statement"": [{
    ""Sid"": """",
    ""Effect"": ""Allow"",
    ""Principal"": {
        ""Service"": ""eks.amazonaws.com""
    },
    ""Action"": ""sts:AssumeRole""
}]
}"
        });

        var eksPolicies = new Dictionary <string, string>
        {
            { "service-policy", "arn:aws:iam::aws:policy/AmazonEKSServicePolicy" },
            { "cluster-policy", "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" }
        };

        foreach (var(name, policy) in eksPolicies)
        {
            var taskExecAttach = new Iam.RolePolicyAttachment($"rpa-{name}",
                                                              new Iam.RolePolicyAttachmentArgs
            {
                Role      = eksRole.Name,
                PolicyArn = policy,
            });
        }

        // Create an IAM role that can be used by our service's task.
        var nodeGroupRole = new Iam.Role("nodegroup-iam-role", new Iam.RoleArgs
        {
            AssumeRolePolicy = @"{
""Version"": ""2008-10-17"",
""Statement"": [{
    ""Sid"": """",
    ""Effect"": ""Allow"",
    ""Principal"": {
        ""Service"": ""ec2.amazonaws.com""
    },
    ""Action"": ""sts:AssumeRole""
}]
}"
        });

        var nodeGroupPolicies = new Dictionary <string, string>
        {
            { "worker", "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" },
            { "cni", "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" },
            { "registry", "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" }
        };

        foreach (var(name, policy) in nodeGroupPolicies)
        {
            var taskExecAttach = new Iam.RolePolicyAttachment($"ngpa-{name}",
                                                              new Iam.RolePolicyAttachmentArgs
            {
                Role      = nodeGroupRole.Name,
                PolicyArn = policy,
            });
        }

        var clusterSg = new Ec2.SecurityGroup("cluster-sg", new Ec2.SecurityGroupArgs
        {
            VpcId  = vpcId,
            Egress =
            {
                new Ec2.Inputs.SecurityGroupEgressArgs
                {
                    Protocol   = "-1",
                    FromPort   = 0,
                    ToPort     = 0,
                    CidrBlocks ={ "0.0.0.0/0"                  }
                }
            },
            Ingress =
            {
                new Ec2.Inputs.SecurityGroupIngressArgs
                {
                    Protocol   = "tcp",
                    FromPort   = 80,
                    ToPort     = 80,
                    CidrBlocks ={ "0.0.0.0/0"                  }
                }
            }
        });

        var cluster = new Eks.Cluster("eks-cluster", new Eks.ClusterArgs
        {
            RoleArn   = eksRole.Arn,
            VpcConfig = new ClusterVpcConfigArgs
            {
                PublicAccessCidrs =
                {
                    "0.0.0.0/0",
                },
                SecurityGroupIds =
                {
                    clusterSg.Id,
                },
                SubnetIds = subnetIds,
            },
        });

        var nodeGroup = new Eks.NodeGroup("node-group", new Eks.NodeGroupArgs
        {
            ClusterName   = cluster.Name,
            NodeGroupName = "demo-eks-nodegroup",
            NodeRoleArn   = nodeGroupRole.Arn,
            SubnetIds     = subnetIds,
            ScalingConfig = new NodeGroupScalingConfigArgs
            {
                DesiredSize = 2,
                MaxSize     = 2,
                MinSize     = 2
            },
        });

        this.Kubeconfig = GenerateKubeconfig(cluster.Endpoint,
                                             cluster.CertificateAuthority.Apply(x => x.Data),
                                             cluster.Name);

        var k8sProvider = new K8s.Provider("k8s-provider", new K8s.ProviderArgs
        {
            KubeConfig = this.Kubeconfig
        }, new CustomResourceOptions
        {
            DependsOn = { nodeGroup },
        });

        var appNamespace = new CoreV1.Namespace("app-ns", new NamespaceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Name = "joe-duffy",
            },
        }, new CustomResourceOptions
        {
            Provider = k8sProvider,
        });

        var appLabels = new InputMap <string>
        {
            { "app", "iac-workshop" }
        };
        var deployment = new AppsV1.Deployment("app-dep", new DeploymentArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Namespace = appNamespace.Metadata.Apply(x => x.Name),
            },
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = appLabels
                },
                Replicas = 1,
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = appLabels
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers =
                        {
                            new ContainerArgs
                            {
                                Name  = "iac-workshop",
                                Image = "jocatalin/kubernetes-bootcamp:v2",
                            }
                        }
                    }
                }
            },
        }, new CustomResourceOptions
        {
            Provider = k8sProvider,
        });

        var service = new CoreV1.Service("app-service", new ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Namespace = appNamespace.Metadata.Apply(x => x.Name),
                Labels    = deployment.Spec.Apply(spec => spec.Template.Metadata.Labels),
            },
            Spec = new ServiceSpecArgs
            {
                Type  = "LoadBalancer",
                Ports =
                {
                    new ServicePortArgs
                    {
                        Port       = 80,
                        TargetPort = 8080
                    },
                },
                Selector = deployment.Spec.Apply(spec => spec.Template.Metadata.Labels)
            },
        }, new CustomResourceOptions
        {
            Provider = k8sProvider,
        });

        this.Url = service.Status.Apply(status => status.LoadBalancer.Ingress[0].Hostname);
    }
Ejemplo n.º 3
0
    public AksCluster(string name, AksClusterArgs args)
        : base("example:component:AksCluster", name)
    {
        var adApp = new Application("app", new ApplicationArgs
        {
            DisplayName = "aks-cosmos"
        }, new CustomResourceOptions {
            Parent = this
        });

        var adSp = new ServicePrincipal("service-principal", new ServicePrincipalArgs
        {
            ApplicationId = adApp.ApplicationId
        }, new CustomResourceOptions {
            Parent = this
        });

        var pw = new RandomPassword("pw", new RandomPasswordArgs
        {
            Length  = 20,
            Special = true
        }, new CustomResourceOptions {
            Parent = this
        });

        var adSpPassword = new ServicePrincipalPassword("sp-password", new ServicePrincipalPasswordArgs
        {
            ServicePrincipalId = adSp.Id,
            Value   = pw.Result,
            EndDate = "2099-01-01T00:00:00Z"
        }, new CustomResourceOptions {
            Parent = this
        });

        var keyPair = new PrivateKey("ssh-key", new PrivateKeyArgs
        {
            Algorithm = "RSA",
            RsaBits   = 4096
        }, new CustomResourceOptions {
            Parent = this
        });

        var k8sCluster = new ManagedCluster(name, new ManagedClusterArgs
        {
            ResourceGroupName = args.ResourceGroupName,
            AddonProfiles     =
            {
                ["KubeDashboard"] = new ManagedClusterAddonProfileArgs {
                    Enabled = true
                }
            },
            AgentPoolProfiles =
            {
                new ManagedClusterAgentPoolProfileArgs
                {
                    Count        = args.NodeCount,
                    VmSize       = args.NodeSize,
                    MaxPods      = 110,
                    Mode         = "System",
                    Name         = "agentpool",
                    OsDiskSizeGB = 30,
                    OsType       = "Linux",
                    Type         = "VirtualMachineScaleSets"
                }
            },
            DnsPrefix         = args.ResourceGroupName,
            EnableRBAC        = true,
            KubernetesVersion = args.KubernetesVersion,
            LinuxProfile      = new ContainerServiceLinuxProfileArgs
            {
                AdminUsername = "******",
                Ssh           = new ContainerServiceSshConfigurationArgs
                {
                    PublicKeys = new ContainerServiceSshPublicKeyArgs
                    {
                        KeyData = keyPair.PublicKeyOpenssh
                    }
                }
            },
            NodeResourceGroup       = $"{name}-node-rg",
            ServicePrincipalProfile = new ManagedClusterServicePrincipalProfileArgs
            {
                ClientId = adApp.ApplicationId,
                Secret   = adSpPassword.Value
            }
        }, new CustomResourceOptions {
            Parent = this
        });

        this.ClusterName = k8sCluster.Name;

        this.KubeConfig = Output.Tuple(k8sCluster.Name, args.ResourceGroupName.ToOutput())
                          .Apply(pair =>
        {
            var k8sClusterName    = pair.Item1;
            var resourceGroupName = pair.Item2;

            return(ListManagedClusterUserCredentials.InvokeAsync(new ListManagedClusterUserCredentialsArgs
            {
                ResourceGroupName = resourceGroupName,
                ResourceName = k8sClusterName
            }));
        })
                          .Apply(x => x.Kubeconfigs[0].Value)
                          .Apply(Convert.FromBase64String)
                          .Apply(Encoding.UTF8.GetString);

        this.Provider = new K8s.Provider("k8s-provider", new K8s.ProviderArgs
        {
            KubeConfig = this.KubeConfig
        }, new CustomResourceOptions {
            Parent = this
        });
    }
Ejemplo n.º 4
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.º 5
0
    public MyCluster(MyConfig cfg)
    {
        var resourceGroup = new ResourceGroup("rg");

        var adApp = new Application("app", new ApplicationArgs
        {
            DisplayName = "app"
        });

        var adSp = new ServicePrincipal("service-principal", new ServicePrincipalArgs
        {
            ApplicationId = adApp.ApplicationId
        });

        var adSpPassword = new ServicePrincipalPassword("sp-password", new ServicePrincipalPasswordArgs
        {
            ServicePrincipalId = adSp.Id,
            Value   = cfg.Password,
            EndDate = "2099-01-01T00:00:00Z"
        });

        var k8sCluster = new ManagedCluster("cluster", new ManagedClusterArgs
        {
            ResourceGroupName = resourceGroup.Name,
            AddonProfiles     =
            {
                ["KubeDashboard"] = new ManagedClusterAddonProfileArgs {
                    Enabled = true
                }
            },
            AgentPoolProfiles =
            {
                new ManagedClusterAgentPoolProfileArgs
                {
                    Count        = cfg.NodeCount,
                    VmSize       = cfg.NodeSize,
                    MaxPods      = 110,
                    Mode         = "System",
                    Name         = "agentpool",
                    OsDiskSizeGB = 30,
                    OsType       = "Linux",
                    Type         = "VirtualMachineScaleSets"
                }
            },
            DnsPrefix         = resourceGroup.Name,
            EnableRBAC        = true,
            KubernetesVersion = cfg.K8SVersion,
            LinuxProfile      = new ContainerServiceLinuxProfileArgs
            {
                AdminUsername = cfg.AdminUserName,
                Ssh           = new ContainerServiceSshConfigurationArgs
                {
                    PublicKeys = new ContainerServiceSshPublicKeyArgs
                    {
                        KeyData = cfg.SshPublicKey
                    }
                }
            },
            NodeResourceGroup       = "node-resource-group",
            ServicePrincipalProfile = new ManagedClusterServicePrincipalProfileArgs
            {
                ClientId = adApp.ApplicationId,
                Secret   = adSpPassword.Value
            }
        });

        this.ClusterName = k8sCluster.Name;

        this.Kubeconfig = ListManagedClusterUserCredentials.Invoke(
            new ListManagedClusterUserCredentialsInvokeArgs
        {
            ResourceGroupName = resourceGroup.Name,
            ResourceName      = k8sCluster.Name
        })
                          .Apply(x => x.Kubeconfigs[0].Value)
                          .Apply(Convert.FromBase64String)
                          .Apply(Encoding.UTF8.GetString);

        this.Provider = new K8s.Provider("k8s-provider", new K8s.ProviderArgs
        {
            KubeConfig = Kubeconfig
        });
    }