Пример #1
0
    static Task <int> Main(string[] args)
    {
        return(Deployment.RunAsync(() =>
        {
            // Minikube does not implement services of type `LoadBalancer`; require the user to
            // specify if we're running on minikube, and if so, create only services of type
            // ClusterIP.
            var config = new Config();
            var isMiniKube = config.GetBoolean("isMiniKube") ?? false;

            //
            // REDIS MASTER.
            //

            var redisMasterLabels = new InputMap <string> {
                { "app", "redis-master" },
            };

            var redisMasterDeployment = new Pulumi.Kubernetes.Apps.V1.Deployment("redis-master", new DeploymentArgs
            {
                Spec = new DeploymentSpecArgs
                {
                    Selector = new LabelSelectorArgs
                    {
                        MatchLabels = redisMasterLabels,
                    },
                    Template = new PodTemplateSpecArgs
                    {
                        Metadata = new ObjectMetaArgs
                        {
                            Labels = redisMasterLabels,
                        },
                        Spec = new PodSpecArgs
                        {
                            Containers =
                            {
                                new ContainerArgs
                                {
                                    Name = "master",
                                    Image = "k8s.gcr.io/redis:e2e",
                                    Resources = new ResourceRequirementsArgs
                                    {
                                        Requests =
                                        {
                                            { "cpu",    "100m"     },
                                            { "memory", "100Mi"    },
                                        },
                                    },
                                    Ports =
                                    {
                                        new ContainerPortArgs {
                                            ContainerPortValue = 6379
                                        }
                                    },
                                },
                            },
                        },
                    },
                },
            });

            var redisMasterService = new Pulumi.Kubernetes.Core.V1.Service("redis-master", new ServiceArgs
            {
                Metadata = new ObjectMetaArgs
                {
                    Name = "redis-master",
                    Labels = redisMasterDeployment.Metadata.Apply(metadata => metadata.Labels),
                },
                Spec = new ServiceSpecArgs
                {
                    Ports =
                    {
                        new ServicePortArgs
                        {
                            Port = 6379,
                            TargetPort = 6379,
                        },
                    },
                    Selector = redisMasterDeployment.Spec.Apply(spec => spec.Template.Metadata.Labels),
                }
            });

            //
            // REDIS REPLICA.
            //

            var redisReplicaLabels = new InputMap <string> {
                { "app", "redis-replica" },
            };

            var redisReplicaDeployment = new Pulumi.Kubernetes.Apps.V1.Deployment("redis-replica", new DeploymentArgs
            {
                Spec = new DeploymentSpecArgs
                {
                    Selector = new LabelSelectorArgs
                    {
                        MatchLabels = redisReplicaLabels,
                    },
                    Template = new PodTemplateSpecArgs
                    {
                        Metadata = new ObjectMetaArgs
                        {
                            Labels = redisReplicaLabels,
                        },
                        Spec = new PodSpecArgs
                        {
                            Containers =
                            {
                                new ContainerArgs
                                {
                                    Name = "replica",
                                    Image = "gcr.io/google_samples/gb-redisslave:v1",
                                    Resources = new ResourceRequirementsArgs
                                    {
                                        Requests =
                                        {
                                            { "cpu",    "100m"     },
                                            { "memory", "100Mi"    },
                                        },
                                    },
                                    // If your cluster config does not include a dns service, then to instead access an environment
                                    // variable to find the master service's host, change `value: "dns"` to read `value: "env"`.
                                    Env =
                                    {
                                        new EnvVarArgs
                                        {
                                            Name = "GET_HOSTS_FROM",
                                            Value = "dns"
                                        },
                                    },
                                    Ports =
                                    {
                                        new ContainerPortArgs {
                                            ContainerPortValue = 6379
                                        }
                                    },
                                },
                            },
                        },
                    },
                },
            });

            var redisReplicaService = new Pulumi.Kubernetes.Core.V1.Service("redis-replica", new ServiceArgs
            {
                Metadata = new ObjectMetaArgs
                {
                    Name = "redis-slave",
                    Labels = redisReplicaDeployment.Metadata.Apply(metadata => metadata.Labels),
                },
                Spec = new ServiceSpecArgs
                {
                    Ports =
                    {
                        new ServicePortArgs
                        {
                            Port = 6379,
                            TargetPort = 6379,
                        },
                    },
                    Selector = redisReplicaDeployment.Spec.Apply(spec => spec.Template.Metadata.Labels),
                }
            });

            //
            // FRONTEND
            //

            var frontendLabels = new InputMap <string> {
                { "app", "frontend" },
            };

            var frontendDeployment = new Pulumi.Kubernetes.Apps.V1.Deployment("frontend", new DeploymentArgs
            {
                Spec = new DeploymentSpecArgs
                {
                    Selector = new LabelSelectorArgs
                    {
                        MatchLabels = frontendLabels,
                    },
                    Replicas = 3,
                    Template = new PodTemplateSpecArgs
                    {
                        Metadata = new ObjectMetaArgs
                        {
                            Labels = frontendLabels,
                        },
                        Spec = new PodSpecArgs
                        {
                            Containers =
                            {
                                new ContainerArgs
                                {
                                    Name = "php-redis",
                                    Image = "gcr.io/google-samples/gb-frontend:v4",
                                    Resources = new ResourceRequirementsArgs
                                    {
                                        Requests =
                                        {
                                            { "cpu",    "100m"     },
                                            { "memory", "100Mi"    },
                                        },
                                    },
                                    // If your cluster config does not include a dns service, then to instead access an environment
                                    // variable to find the master service's host, change `value: "dns"` to read `value: "env"`.
                                    Env =
                                    {
                                        new EnvVarArgs
                                        {
                                            Name = "GET_HOSTS_FROM",
                                            Value = "dns", /* Value = "env"*/
                                        },
                                    },
                                    Ports =
                                    {
                                        new ContainerPortArgs {
                                            ContainerPortValue = 80
                                        }
                                    },
                                },
                            },
                        },
                    },
                },
            });

            var frontendService = new Pulumi.Kubernetes.Core.V1.Service("frontend", new ServiceArgs
            {
                Metadata = new ObjectMetaArgs
                {
                    Name = "frontend",
                    Labels = frontendDeployment.Metadata.Apply(metadata => metadata.Labels),
                },
                Spec = new ServiceSpecArgs
                {
                    Type = isMiniKube ? "ClusterIP" : "LoadBalancer",
                    Ports =
                    {
                        new ServicePortArgs
                        {
                            Port = 80,
                            TargetPort = 80,
                        },
                    },
                    Selector = frontendDeployment.Spec.Apply(spec => spec.Template.Metadata.Labels),
                }
            });

            Output <string> frontendIP;
            if (isMiniKube)
            {
                frontendIP = frontendService.Spec.Apply(spec => spec.ClusterIP);
            }
            else
            {
                frontendIP = frontendService.Status.Apply(status => status.LoadBalancer.Ingress[0].Hostname);
            }

            return new Dictionary <string, object> {
                { "frontendIp", frontendIP },
            };
        }));
    }
Пример #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);
    }
Пример #3
0
    public MyStack()
    {
        var ns = new K8s.Core.V1.Namespace("app-ns", new K8s.Types.Inputs.Core.V1.NamespaceArgs
        {
            Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs {
                Name = "my-name"
            }
        });

        var appLabels = new InputMap <string> {
            { "app", "iac-workshop" }
        };
        var deployment = new K8s.Apps.V1.Deployment("app-dep", new K8s.Types.Inputs.Apps.V1.DeploymentArgs
        {
            Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs {
                Namespace = ns.Metadata.Apply(m => m.Name)
            },
            Spec = new K8s.Types.Inputs.Apps.V1.DeploymentSpecArgs
            {
                Selector = new K8s.Types.Inputs.Meta.V1.LabelSelectorArgs {
                    MatchLabels = appLabels
                },
                Replicas = 1,
                Template = new K8s.Types.Inputs.Core.V1.PodTemplateSpecArgs
                {
                    Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs {
                        Labels = appLabels
                    },
                    Spec = new K8s.Types.Inputs.Core.V1.PodSpecArgs
                    {
                        Containers =
                        {
                            new K8s.Types.Inputs.Core.V1.ContainerArgs
                            {
                                Name  = "iac-workshop",
                                Image = "gcr.io/google-samples/kubernetes-bootcamp:v1"
                            }
                        }
                    }
                }
            }
        });

        var service = new K8s.Core.V1.Service("app-svc", new K8s.Types.Inputs.Core.V1.ServiceArgs
        {
            Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs {
                Namespace = ns.Metadata.Apply(m => m.Name)
            },
            Spec = new K8s.Types.Inputs.Core.V1.ServiceSpecArgs
            {
                Selector = appLabels,
                Ports    = { new K8s.Types.Inputs.Core.V1.ServicePortArgs {
                                 Port = 80, TargetPort = 8080
                             } },
                Type = "LoadBalancer"
            }
        });

        var address = service.Status
                      .Apply(s => s.LoadBalancer)
                      .Apply(lb => lb.Ingress)
                      .GetAt(0)
                      .Apply(i => i.Ip);

        this.Url = Output.Format($"http://{address}");
    }
Пример #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);
    }
Пример #5
0
    public ServiceDeployment(string name, ServiceDeploymentArgs args, ComponentResourceOptions?opts = null)
        : base(name, "k8sx:service:ServiceDeployment", opts)
    {
        var labels = new InputMap <string>
        {
            { "app", name },
        };

        var deploymentPorts = args.Ports.ToOutput().Apply(ports =>
                                                          from p in ports select new ContainerPortArgs {
            ContainerPortValue = 6379
        }
                                                          );

        var container = new ContainerArgs
        {
            Name      = name,
            Image     = args.Image,
            Resources = args.Resources ?? new ResourceRequirementsArgs
            {
                Requests =
                {
                    { "cpu",    "100m"  },
                    { "memory", "100Mi" },
                },
            },
            Env   = args.Env,
            Ports = deploymentPorts,
        };

        this.Deployment = new Pulumi.Kubernetes.Apps.V1.Deployment(name, new DeploymentArgs
        {
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = labels,
                },
                Replicas = args.Replicas ?? 1,
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = labels,
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers = { container },
                    },
                },
            },
        },
                                                                   new CustomResourceOptions {
            Parent = this
        });

        var servicePorts = args.Ports.ToOutput().Apply(ports =>
                                                       from p in ports select new ServicePortArgs {
            Port = p, TargetPort = p
        }
                                                       );

        this.Service = new Pulumi.Kubernetes.Core.V1.Service(name, new ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Name   = name,
                Labels = this.Deployment.Metadata.Apply(metadata => metadata.Labels),
            },
            Spec = new ServiceSpecArgs
            {
                Type     = args.AllocateIPAddress.Apply(hasIp => hasIp ? (args.ServiceType ?? "LoadBalancer") : null),
                Ports    = servicePorts,
                Selector = this.Deployment.Spec.Apply(spec => spec.Template.Metadata.Labels),
            },
        },
                                                             new CustomResourceOptions {
            Parent = this
        });

        this.IpAddress = args.AllocateIPAddress.Apply(hasIp =>
        {
            if (hasIp)
            {
                return(args.ServiceType.Apply(serviceType =>
                                              serviceType == "ClusterIP"
                    ? this.Service.Spec.Apply(s => s.ClusterIP)
                    : this.Service.Status.Apply(status =>
                {
                    var ingress = status.LoadBalancer.Ingress[0];
                    // Return the ip address if populated or else the hostname
                    return ingress.Ip ?? ingress.Hostname;
                })
                                              ));
            }
            else
            {
                return(null);
            }
        });
    }
Пример #6
0
    static Task <int> Main() => Deployment.RunAsync(async() => {
        // Create a private GCR registry.
        var registry    = new Registry("my-registry");
        var registryUrl = registry.Id.Apply(async _ => {
            return((await GetRegistryRepository.InvokeAsync()).RepositoryUrl);
        });

        // Get registry info (creds and endpoint).
        var imageName = Output.Format($"{registryUrl}/myapp");
        //var registryInfo = new ImageRegistry(); // use gcloud for authentication.

        // Build and publish the app image.
        var image = new Image("my-image", new ImageArgs
        {
            Build = new DockerBuild {
                Context = "app"
            },
            ImageName = imageName,
            //Registry = registryInfo,
        });

        // Create a load balanced Kubernetes service using this image, and export its IP.
        var appLabels = new InputMap <string>
        {
            { "app", "myapp" }
        };
        var appDep = new Pulumi.Kubernetes.Apps.V1.Deployment("app-dep", new DeploymentArgs
        {
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = appLabels
                },
                Replicas = 3,
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = appLabels,
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers =
                        {
                            new Pulumi.Kubernetes.Types.Inputs.Core.V1.ContainerArgs
                            {
                                Name  = "myapp",
                                Image = image.ImageName,
                            }
                        }
                    }
                }
            }
        });
        var appSvc = new Pulumi.Kubernetes.Core.V1.Service("app-svc", new Pulumi.Kubernetes.Types.Inputs.Core.V1.ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Labels = appLabels
            },
            Spec = new ServiceSpecArgs
            {
                Type  = "LoadBalancer",
                Ports =
                {
                    new ServicePortArgs
                    {
                        Port       = 80,
                        TargetPort = 80
                    }
                },
                Selector = appLabels
            }
        });

        // Export the resulting base name in addition to the specific version pushed.
        return(new Dictionary <string, object>
        {
            { "baseImageName", image.BaseImageName },
            { "fullImageName", image.ImageName },
            { "appIp", appSvc.Status.Apply(status => status.LoadBalancer.Ingress[0].Ip) },
        });
    });
        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);
        }
Пример #8
0
    public Guestbook()
    {
        // Minikube does not implement services of type `LoadBalancer`; require the user to
        // specify if we're running on minikube, and if so, create only services of type
        // ClusterIP.
        var config     = new Config();
        var isMiniKube = config.GetBoolean("isMiniKube") ?? false;

        //
        // REDIS MASTER.
        //

        var redisLeaderLabels = new InputMap <string>
        {
            { "app", "redis-leader" }
        };

        var redisLeaderDeployment = new Pulumi.Kubernetes.Apps.V1.Deployment("redis-leader", new DeploymentArgs
        {
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = redisLeaderLabels
                },
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = redisLeaderLabels
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers =
                        {
                            new ContainerArgs
                            {
                                Name      = "redis-leader",
                                Image     = "redis",
                                Resources = new ResourceRequirementsArgs
                                {
                                    Requests =
                                    {
                                        { "cpu",    "100m"     },
                                        { "memory", "100Mi"    }
                                    }
                                },
                                Ports =
                                {
                                    new ContainerPortArgs {
                                        ContainerPortValue = 6379
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });

        var redisLeaderService = new Pulumi.Kubernetes.Core.V1.Service("redis-leader", new ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Name   = "redis-leader",
                Labels = redisLeaderDeployment.Metadata.Apply(metadata => metadata.Labels),
            },
            Spec = new ServiceSpecArgs
            {
                Ports =
                {
                    new ServicePortArgs
                    {
                        Port       = 6379,
                        TargetPort = 6379
                    },
                },
                Selector = redisLeaderDeployment.Spec.Apply(spec => spec.Template.Metadata.Labels)
            }
        });

        //
        // REDIS REPLICA.
        //

        var redisReplicaLabels = new InputMap <string>
        {
            { "app", "redis-replica" }
        };

        var redisReplicaDeployment = new Pulumi.Kubernetes.Apps.V1.Deployment("redis-replica", new DeploymentArgs
        {
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = redisReplicaLabels
                },
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = redisReplicaLabels
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers =
                        {
                            new ContainerArgs
                            {
                                Name      = "redis-replica",
                                Image     = "pulumi/guestbook-redis-replica",
                                Resources = new ResourceRequirementsArgs
                                {
                                    Requests =
                                    {
                                        { "cpu",    "100m"     },
                                        { "memory", "100Mi"    }
                                    }
                                },
                                // If your cluster config does not include a dns service, then to instead access an environment
                                // variable to find the leader's host, change `value: "dns"` to read `value: "env"`.
                                Env =
                                {
                                    new EnvVarArgs
                                    {
                                        Name  = "GET_HOSTS_FROM",
                                        Value = "dns"
                                    },
                                },
                                Ports =
                                {
                                    new ContainerPortArgs {
                                        ContainerPortValue = 6379
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });

        var redisReplicaService = new Pulumi.Kubernetes.Core.V1.Service("redis-replica", new ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Name   = "redis-replica",
                Labels = redisReplicaDeployment.Metadata.Apply(metadata => metadata.Labels)
            },
            Spec = new ServiceSpecArgs
            {
                Ports =
                {
                    new ServicePortArgs
                    {
                        Port       = 6379,
                        TargetPort = 6379
                    },
                },
                Selector = redisReplicaDeployment.Spec.Apply(spec => spec.Template.Metadata.Labels)
            }
        });

        //
        // FRONTEND
        //

        var frontendLabels = new InputMap <string>
        {
            { "app", "frontend" },
        };

        var frontendDeployment = new Pulumi.Kubernetes.Apps.V1.Deployment("frontend", new DeploymentArgs
        {
            Spec = new DeploymentSpecArgs
            {
                Selector = new LabelSelectorArgs
                {
                    MatchLabels = frontendLabels
                },
                Replicas = 3,
                Template = new PodTemplateSpecArgs
                {
                    Metadata = new ObjectMetaArgs
                    {
                        Labels = frontendLabels
                    },
                    Spec = new PodSpecArgs
                    {
                        Containers =
                        {
                            new ContainerArgs
                            {
                                Name      = "php-redis",
                                Image     = "pulumi/guestbook-php-redis",
                                Resources = new ResourceRequirementsArgs
                                {
                                    Requests =
                                    {
                                        { "cpu",    "100m"     },
                                        { "memory", "100Mi"    },
                                    },
                                },
                                // If your cluster config does not include a dns service, then to instead access an environment
                                // variable to find the master service's host, change `value: "dns"` to read `value: "env"`.
                                Env =
                                {
                                    new EnvVarArgs
                                    {
                                        Name  = "GET_HOSTS_FROM",
                                        Value = "dns", /* Value = "env"*/
                                    }
                                },
                                Ports =
                                {
                                    new ContainerPortArgs {
                                        ContainerPortValue = 80
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });

        var frontendService = new Pulumi.Kubernetes.Core.V1.Service("frontend", new ServiceArgs
        {
            Metadata = new ObjectMetaArgs
            {
                Name   = "frontend",
                Labels = frontendDeployment.Metadata.Apply(metadata => metadata.Labels)
            },
            Spec = new ServiceSpecArgs
            {
                Type  = isMiniKube ? "ClusterIP" : "LoadBalancer",
                Ports =
                {
                    new ServicePortArgs
                    {
                        Port       = 80,
                        TargetPort = 80
                    }
                },
                Selector = frontendDeployment.Spec.Apply(spec => spec.Template.Metadata.Labels)
            }
        });

        if (isMiniKube)
        {
            this.FrontendIp = frontendService.Spec.Apply(spec => spec.ClusterIP);
        }
        else
        {
            this.FrontendIp = frontendService.Status.Apply(status => status.LoadBalancer.Ingress[0].Ip ?? status.LoadBalancer.Ingress[0].Hostname);
        }
    }