2019-10-16 13:05:14 -07:00
|
|
|
---
|
2023-06-02 21:41:36 -07:00
|
|
|
title_tag: Deploy Kubernetes App Services | Crosswalk
|
2019-12-18 09:59:20 -08:00
|
|
|
meta_desc: This page provides an overview of how to deploy Kubernetes App services to different
|
|
|
|
cloud providers.
|
2023-05-15 15:25:28 -07:00
|
|
|
title: App services
|
|
|
|
h1: Kubernetes App services
|
2023-06-08 16:15:52 -07:00
|
|
|
meta_image: /images/docs/meta-images/docs-clouds-kubernetes-meta-image.png
|
2019-10-16 13:05:14 -07:00
|
|
|
menu:
|
2023-05-15 15:25:28 -07:00
|
|
|
clouds:
|
|
|
|
parent: kubernetes-guides
|
|
|
|
identifier: kubernetes-guides-app-svcs
|
2019-11-16 12:40:48 -08:00
|
|
|
weight: 8
|
2023-05-15 15:25:28 -07:00
|
|
|
aliases:
|
|
|
|
- /docs/guides/crosswalk/kubernetes/app-services/
|
2019-10-16 13:05:14 -07:00
|
|
|
---
|
|
|
|
|
2020-03-23 21:06:03 -07:00
|
|
|
{{< chooser cloud "aws,azure,gcp" / >}}
|
2019-10-17 13:32:41 -07:00
|
|
|
|
2019-10-24 19:12:44 -07:00
|
|
|
App services are general services scoped at the Kubernetes application level.
|
|
|
|
These services tend to include datastores, and managers for ingress, DNS, and TLS.
|
|
|
|
They can be shared amongst several apps or be specific to workloads, and are
|
|
|
|
usually a mix of cloud provider and custom services.
|
2019-10-24 18:58:12 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable cloud aws %}}
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2022-01-18 13:47:38 -08:00
|
|
|
* [AWS app services stack on GitHub](https://github.com/pulumi/kubernetes-guides/tree/master/aws/05-app-services)
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable cloud azure %}}
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2022-01-18 13:47:38 -08:00
|
|
|
* [Azure app services stack on GitHub](https://github.com/pulumi/kubernetes-guides/tree/master/azure/05-app-services)
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable cloud gcp %}}
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2023-05-15 15:25:28 -07:00
|
|
|
* [Google Cloud app services stack on GitHub](https://github.com/pulumi/kubernetes-guides/tree/master/gcp/05-app-services)
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
|
|
|
|
2022-01-18 13:47:38 -08:00
|
|
|
* [General app services stack on GitHub](https://github.com/pulumi/kubernetes-guides/tree/master/general-app-services)
|
2019-11-08 21:31:35 -08:00
|
|
|
|
2019-10-24 19:12:44 -07:00
|
|
|
## Overview
|
|
|
|
|
|
|
|
We'll explore how to setup:
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
* [Datastores](#datastores)
|
|
|
|
* [General App Services](#general-app-services)
|
2019-10-17 13:32:41 -07:00
|
|
|
|
2019-11-08 01:00:31 -08:00
|
|
|
## Prerequisites
|
|
|
|
|
2020-03-23 21:06:03 -07:00
|
|
|
{{< chooser cloud "aws,azure,gcp" / >}}
|
2020-03-20 09:32:19 -07:00
|
|
|
|
|
|
|
{{% choosable cloud aws %}}
|
2019-11-08 01:00:31 -08:00
|
|
|
|
|
|
|
Authenticate as the `admins` role from the [Identity][aws-admin-identity-stack] stack.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ aws sts assume-role --role-arn `pulumi stack output adminsIamRoleArn` --role-session-name k8s-admin
|
|
|
|
$ export KUBECONFIG=`pwd`/kubeconfig-admin.json
|
|
|
|
```
|
2019-12-18 09:59:20 -08:00
|
|
|
|
2023-05-15 15:25:28 -07:00
|
|
|
[aws-admin-identity-stack]: /docs/clouds/kubernetes/guides/identity#create-an-iam-role-for-admins/
|
2020-03-20 09:32:19 -07:00
|
|
|
|
|
|
|
{{% /choosable %}}
|
|
|
|
|
|
|
|
{{% choosable cloud azure %}}
|
|
|
|
|
2019-11-08 01:00:31 -08:00
|
|
|
Authenticate as the ServicePrincipal from the [Identity][azure-identity-stack] stack.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ az login --service-principal --username $ARM_CLIENT_ID --password $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID
|
|
|
|
$ export KUBECONFIG=`pwd`/kubeconfig-admin.json
|
|
|
|
```
|
2019-12-18 09:59:20 -08:00
|
|
|
|
2023-05-15 15:25:28 -07:00
|
|
|
[azure-identity-stack]: /docs/clouds/kubernetes/guides/identity/
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
|
|
|
|
|
|
|
{{% choosable cloud gcp %}}
|
|
|
|
|
2019-11-08 01:00:31 -08:00
|
|
|
Authenticate as the `admins` ServiceAccount from the [Identity][gcp-admin-identity-stack] stack.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ gcloud auth activate-service-account --key-file k8s-admin-sa-key.json
|
|
|
|
$ export KUBECONFIG=`pwd`/kubeconfig.json
|
|
|
|
```
|
|
|
|
|
2023-05-15 15:25:28 -07:00
|
|
|
[gcp-admin-identity-stack]: /docs/clouds/kubernetes/guides/identity/#create-an-iam-role-for-admins
|
2020-03-20 09:32:19 -07:00
|
|
|
|
|
|
|
{{% /choosable %}}
|
|
|
|
|
2019-10-23 15:58:46 -07:00
|
|
|
## Datastores
|
|
|
|
|
2019-10-24 19:12:44 -07:00
|
|
|
Apps may want to persist data to databases or in-memory datastores. Often
|
|
|
|
times these services are provisioned directly with the cloud provider to simplify
|
|
|
|
running and managing their lifecycles.
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable cloud aws %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
### Postgres Database
|
2019-10-24 19:12:44 -07:00
|
|
|
|
|
|
|
Create a Postgres database instance in [AWS RDS][aws-rds], and store its
|
|
|
|
connection information in a Kubernetes [Secret][k8s-secret] for apps to refer
|
|
|
|
to and consume.
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
import * as aws from "@pulumi/aws";
|
|
|
|
import * as random from "@pulumi/random";
|
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
|
|
|
|
// Generate a strong password for the Postgres DB.
|
|
|
|
const postgresDbPassword = new random.RandomString(`${projectName}-db-password`, {
|
|
|
|
length: 20,
|
|
|
|
special: true
|
|
|
|
}, {additionalSecretOutputs: ["result"]}).result;
|
|
|
|
|
|
|
|
// Create a Postgres DB instance of RDS.
|
|
|
|
const dbSubnets = new aws.rds.SubnetGroup(`${projectName}-subnets`, {
|
|
|
|
subnetIds: privateSubnetIds
|
|
|
|
});
|
|
|
|
const db = new aws.rds.Instance("postgresdb", {
|
|
|
|
engine: "postgres",
|
|
|
|
instanceClass: "db.t2.micro",
|
|
|
|
allocatedStorage: 20,
|
|
|
|
dbSubnetGroupName: dbSubnets.id,
|
|
|
|
vpcSecurityGroupIds: securityGroupIds,
|
|
|
|
name: "testdb",
|
|
|
|
username: "alice",
|
|
|
|
password: postgresDbPassword,
|
|
|
|
skipFinalSnapshot: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a Secret from the DB connection information.
|
2019-10-25 18:53:40 -07:00
|
|
|
const provider = new k8s.Provider("eks-provider", {kubeconfig: config.kubeconfig.apply(JSON.stringify)});
|
2019-10-24 19:12:44 -07:00
|
|
|
const dbConn = new k8s.core.v1.Secret("postgres-db-conn",
|
|
|
|
{
|
|
|
|
data: {
|
|
|
|
host: db.address.apply(addr => Buffer.from(addr).toString("base64")),
|
|
|
|
port: db.port.apply(port => Buffer.of(port).toString("base64")),
|
|
|
|
username: db.username.apply(user => Buffer.from(user).toString("base64")),
|
|
|
|
password: postgresDbPassword.apply(pass => Buffer.from(pass).toString("base64")),
|
|
|
|
},
|
|
|
|
},
|
2019-10-25 18:53:40 -07:00
|
|
|
{provider: provider},
|
2019-10-24 19:12:44 -07:00
|
|
|
);
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
### Redis Datastore
|
2019-10-24 19:12:44 -07:00
|
|
|
|
|
|
|
Create a Redis datastore instance in [AWS ElastiCache][aws-ec], and store its
|
|
|
|
connection information in a Kubernetes [ConfigMap][k8s-cm] for apps to refer
|
|
|
|
to and consume.
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
import * as aws from "@pulumi/aws";
|
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
|
|
|
|
// Create a Redis instance.
|
|
|
|
const cacheSubnets = new aws.elasticache.SubnetGroup(`${projectName}-cache-subnets`, {
|
|
|
|
subnetIds: privateSubnetIds,
|
|
|
|
});
|
|
|
|
const cacheCluster = new aws.elasticache.Cluster("cachecluster", {
|
|
|
|
engine: "redis",
|
|
|
|
nodeType: "cache.t2.micro",
|
|
|
|
numCacheNodes: 1,
|
|
|
|
subnetGroupName: cacheSubnets.id,
|
|
|
|
securityGroupIds: securityGroupIds,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a ConfigMap from the cache connection information.
|
2020-04-11 21:43:41 +01:00
|
|
|
const cacheConn = new k8s.core.v1.ConfigMap("redis-db-conn",
|
2019-10-24 19:12:44 -07:00
|
|
|
{
|
|
|
|
data: {
|
|
|
|
host: cacheCluster.cacheNodes[0].address.apply(addr => Buffer.from(addr).toString("base64")),
|
|
|
|
},
|
|
|
|
},
|
2019-10-25 18:53:40 -07:00
|
|
|
{provider: provider},
|
2019-10-24 19:12:44 -07:00
|
|
|
);
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2019-10-24 19:12:44 -07:00
|
|
|
[k8s-secret]: https://kubernetes.io/docs/concepts/configuration/secret/
|
|
|
|
[k8s-cm]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
|
|
|
|
[aws-ec]: https://aws.amazon.com/elasticache/
|
|
|
|
[aws-rds]: https://aws.amazon.com/rds/
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable cloud azure %}}
|
2019-11-09 18:38:58 -08:00
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
### MongoDB
|
2019-11-09 19:01:15 -08:00
|
|
|
|
|
|
|
Create a MongoDB database instance in [Azure CosmosDB][azure-cosmosdb], and store its
|
|
|
|
connection information in a Kubernetes [Secret][k8s-secret] for apps to refer
|
|
|
|
to and consume.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
import * as azure from "@pulumi/azure";
|
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
import * as pulumi from "@pulumi/pulumi";
|
|
|
|
|
|
|
|
const name = pulumi.getProject();
|
|
|
|
|
|
|
|
// Define a separate resource group for app services.
|
|
|
|
const resourceGroup = new azure.core.ResourceGroup(name);
|
|
|
|
|
|
|
|
// Create a MongoDB-flavored instance of CosmosDB.
|
|
|
|
const cosmosdb = new azure.cosmosdb.Account("k8s-az-mongodb", {
|
|
|
|
resourceGroupName: resourceGroup.name,
|
|
|
|
kind: "MongoDB",
|
|
|
|
consistencyPolicy: {
|
|
|
|
consistencyLevel: "Session",
|
|
|
|
},
|
|
|
|
offerType: "Standard",
|
|
|
|
geoLocations: [
|
|
|
|
{ location: resourceGroup.location, failoverPriority: 0 },
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
// A k8s provider instance of the cluster.
|
|
|
|
const provider = new k8s.Provider(`${name}-aks`, {
|
|
|
|
kubeconfig: config.kubeconfig,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create secret from MongoDB connection string.
|
|
|
|
const mongoConnStrings = new k8s.core.v1.Secret(
|
|
|
|
"mongo-secrets",
|
|
|
|
{
|
|
|
|
metadata: { name: "mongo-secrets", namespace: config.appsNamespaceName},
|
|
|
|
data: mongoHelpers.parseConnString(cosmosdb.connectionStrings),
|
|
|
|
},
|
|
|
|
{ provider },
|
|
|
|
);
|
|
|
|
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2019-11-09 19:01:15 -08:00
|
|
|
[azure-cosmosdb]: https://azure.microsoft.com/en-us/services/cosmos-db/
|
|
|
|
[k8s-secret]: https://kubernetes.io/docs/concepts/configuration/secret/
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable cloud gcp %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
### Postgres Database
|
2019-11-09 19:01:15 -08:00
|
|
|
|
|
|
|
Create a Postgres database instance in [CloudSQL][gcp-cloudsql], and store its
|
|
|
|
connection information in a Kubernetes [Secret][k8s-secret] for apps to refer
|
|
|
|
to and consume.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
import * as gcp from "@pulumi/gcp";
|
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
import * as random from "@pulumi/random";
|
|
|
|
|
|
|
|
// Generate a strong password for the Postgres DB.
|
|
|
|
const postgresDbPassword = new random.RandomString(
|
|
|
|
`${projectName}-db-password`,
|
|
|
|
{
|
|
|
|
length: 20,
|
|
|
|
special: true,
|
|
|
|
},
|
|
|
|
{ additionalSecretOutputs: ["result"] },
|
|
|
|
).result;
|
|
|
|
|
|
|
|
// Create a Postgres DB instance.
|
|
|
|
const db = new gcp.sql.DatabaseInstance("postgresdb", {
|
|
|
|
project: config.project,
|
|
|
|
region: "us-west1",
|
|
|
|
databaseVersion: "POSTGRES_9_6",
|
|
|
|
settings: { tier: "db-f1-micro" },
|
|
|
|
});
|
|
|
|
|
|
|
|
// Configure a new SQL user.
|
|
|
|
const user = new gcp.sql.User("default", {
|
|
|
|
project: config.project,
|
|
|
|
instance: db.name,
|
|
|
|
password: postgresDbPassword,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a new k8s provider.
|
|
|
|
const provider = new k8s.Provider("provider", {
|
|
|
|
kubeconfig: config.kubeconfig,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a Secret from the DB connection information.
|
|
|
|
const dbConn = new k8s.core.v1.Secret(
|
|
|
|
"postgres-db-conn",
|
|
|
|
{
|
|
|
|
data: {
|
|
|
|
host: db.privateIpAddress.apply(addr => Buffer.from(addr).toString("base64")),
|
|
|
|
port: Buffer.from("5432").toString("base64"),
|
|
|
|
username: user.name.apply(user => Buffer.from(user).toString("base64")),
|
|
|
|
password: postgresDbPassword.apply(pass => Buffer.from(pass).toString("base64")),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ provider: provider },
|
|
|
|
);
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
### Redis Datastore
|
2019-11-09 19:01:15 -08:00
|
|
|
|
2023-05-15 15:25:28 -07:00
|
|
|
Create a Redis datastore instance in [Google Cloud MemoryStore][gcp-redis], and store its
|
2019-11-09 19:01:15 -08:00
|
|
|
connection information in a Kubernetes [ConfigMap][k8s-cm] for apps to refer
|
|
|
|
to and consume.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
import * as gcp from "@pulumi/gcp";
|
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
|
|
|
|
// Create a Redis instance.
|
|
|
|
const cache = new gcp.redis.Instance("redis", {
|
|
|
|
tier: "STANDARD_HA",
|
|
|
|
memorySizeGb: 1,
|
|
|
|
redisVersion: "REDIS_3_2",
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a ConfigMap from the cache connection information.
|
|
|
|
const cacheConn = new k8s.core.v1.ConfigMap(
|
|
|
|
"postgres-db-conn",
|
|
|
|
{
|
|
|
|
data: {
|
|
|
|
host: cache.host.apply(addr => Buffer.from(addr).toString("base64")),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ provider: provider },
|
|
|
|
);
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2019-11-09 19:01:15 -08:00
|
|
|
[k8s-cm]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
|
|
|
|
[k8s-secret]: https://kubernetes.io/docs/concepts/configuration/secret/
|
|
|
|
[gcp-redis]: https://cloud.google.com/memorystore/
|
|
|
|
[gcp-cloudsql]: https://cloud.google.com/sql/
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2019-10-24 19:12:44 -07:00
|
|
|
## General App Services
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2022-01-18 13:47:38 -08:00
|
|
|
[General app services stack on GitHub](https://github.com/pulumi/kubernetes-guides/tree/master/general-app-services)
|
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
### NGINX Ingress Controller
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
The [NGINX Ingress Controller][nginx] is a custom Kubernetes [Controller][k8s-controller].
|
|
|
|
It manages [L7 network ingress][nginx-l7] / [north-south traffic][ns-traffic]
|
|
|
|
between external clients, and the servers in the cluster's apps.
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2019-10-25 18:53:40 -07:00
|
|
|
[nginx]: https://github.com/kubernetes/ingress-nginx
|
|
|
|
[k8s-controller]: https://kubernetes.io/docs/concepts/architecture/controller/
|
|
|
|
[nginx-l7]: https://www.nginx.com/resources/glossary/layer-7-load-balancing/
|
|
|
|
[ns-traffic]: https://networkengineering.stackexchange.com/a/18877
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
#### Install NGINX
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{< chooser k8s-language "typescript,yaml" >}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable k8s-language yaml %}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
Deploy the [example YAML manifests][nginx-yaml] into the `ingress-nginx` namespace, and publicly expose it to the
|
|
|
|
Internet using a [load balanced Service][k8s-lb-svc].
|
|
|
|
|
2019-11-07 11:38:26 -08:00
|
|
|
> Note: NGINX requires a privileged PSP given its [use][nginx-priv-use] of `allowPrivilegeEscalation: true`.
|
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
```bash
|
2020-06-22 14:27:08 -07:00
|
|
|
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/cloud-generic.yaml
|
2019-10-25 18:53:40 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
Check that the NGINX deployment is running.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ kubectl get pods -n ingress-nginx
|
|
|
|
NAME READY STATUS RESTARTS AGE
|
|
|
|
nginx-ingress-controller-7dcc95dfbf-k99k6 1/1 Running 0 21s
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2020-06-23 13:37:13 -07:00
|
|
|
[nginx-priv-use]: https://github.com/kubernetes/ingress-nginx/blob/nginx-0.30.0/deploy/static/mandatory.yaml#L229
|
2019-10-25 18:53:40 -07:00
|
|
|
[nginx-yaml]: https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#prerequisite-generic-deployment-command
|
|
|
|
[k8s-lb-svc]: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable k8s-language typescript %}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
Deploy the [Helm chart][nginx-helm] into the `app-svcs` namespace created in [Configure
|
|
|
|
Cluster Defaults][crosswalk-k8s-defaults], and publicly expose it to the
|
|
|
|
Internet using a [load balanced Service][k8s-lb-svc].
|
|
|
|
|
2019-11-07 11:38:26 -08:00
|
|
|
> Note: NGINX requires a privileged PSP given its [use][nginx-priv-use] of `allowPrivilegeEscalation: true`.
|
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
```typescript
|
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
|
|
|
|
// Deploy the NGINX ingress controller using the Helm chart.
|
2020-11-14 14:01:30 -08:00
|
|
|
const nginx = new k8s.helm.v3.Chart("nginx",
|
2019-10-25 18:53:40 -07:00
|
|
|
{
|
|
|
|
namespace: config.appSvcsNamespaceName,
|
|
|
|
chart: "nginx-ingress",
|
|
|
|
version: "1.24.4",
|
2021-03-12 09:07:00 -06:00
|
|
|
fetchOpts: {repo: "https://charts.helm.sh/stable/"},
|
2019-10-25 18:53:40 -07:00
|
|
|
values: {controller: {publishService: {enabled: true}}},
|
|
|
|
transformations: [
|
|
|
|
(obj: any) => {
|
|
|
|
// Do transformations on the YAML to set the namespace
|
|
|
|
if (obj.metadata) {
|
|
|
|
obj.metadata.namespace = config.appSvcsNamespaceName;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{providers: {kubernetes: provider}},
|
|
|
|
);
|
|
|
|
```
|
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2019-11-07 11:38:26 -08:00
|
|
|
[nginx-priv-use]: https://github.com/helm/charts/blob/master/stable/nginx-ingress/values.yaml#L12
|
2019-10-25 18:53:40 -07:00
|
|
|
[k8s-lb-svc]: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
|
|
|
|
[nginx-helm]: https://github.com/helm/charts/tree/master/stable/nginx-ingress
|
2023-05-15 15:25:28 -07:00
|
|
|
[crosswalk-k8s-defaults]: /docs/clouds/kubernetes/guides/configure-defaults/#namespaces
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
|
|
|
|
|
|
|
{{< /chooser >}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
#### Deploy a Workload
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
Deploy a [kuard][k8s-kuard] Pod, service, and ingress resources to
|
|
|
|
test the NGINX ingress controller.
|
|
|
|
|
|
|
|
Create the [ingress][k8s-ingress] resource for kuard that NGINX will manage by
|
|
|
|
keying off the `ingress.class` used.
|
|
|
|
|
|
|
|
NGINX will front the app through it's desired host and paths, and the apps are
|
|
|
|
will be accessible to the public internet as they share the public load balancer
|
|
|
|
endpoint provisioned for NGINX's service.
|
|
|
|
|
|
|
|
Traffic is then routed to the app by inspecting the host headers and paths
|
|
|
|
expected by NGINX onto the service that the kuard Pod runs.
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{< chooser k8s-language "typescript,yaml" >}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable k8s-language yaml %}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
```bash
|
|
|
|
$ kubectl run --generator=run-pod/v1 kuard --namespace=`pulumi stack output appsNamespaceName` --image=gcr.io/kuar-demo/kuard-amd64:blue --port=8080 --expose
|
|
|
|
```
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ cat > ingress.yaml << EOF
|
|
|
|
apiVersion: networking.k8s.io/v1beta1
|
|
|
|
kind: Ingress
|
|
|
|
metadata:
|
|
|
|
name: kuard
|
|
|
|
labels:
|
|
|
|
app: kuard
|
|
|
|
annotations:
|
|
|
|
kubernetes.io/ingress.class: nginx
|
|
|
|
spec:
|
|
|
|
rules:
|
|
|
|
- host: apps.example.com
|
|
|
|
http:
|
|
|
|
paths:
|
|
|
|
- path: "/"
|
|
|
|
backend:
|
|
|
|
serviceName: kuard
|
|
|
|
servicePort: http
|
|
|
|
EOF
|
|
|
|
```
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ kubectl apply -f ingress.yaml --namespace=`pulumi stack output appsNamespaceName`
|
|
|
|
```
|
|
|
|
|
2019-11-06 17:56:56 -08:00
|
|
|
Check that the ingress is created, and after a few moments the `Address` will
|
|
|
|
be set to the NGINX LoadBalancer Service address.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ kubectl describe ingress kuard --namespace=`pulumi stack output appsNamespaceName`
|
|
|
|
```
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
2019-10-23 15:58:46 -07:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% choosable k8s-language typescript %}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
```typescript
|
2019-11-04 19:21:58 -08:00
|
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
// Create a kuard Deployment
|
|
|
|
const name = "kuard"
|
|
|
|
const labels = {app: name}
|
|
|
|
const deployment = new k8s.apps.v1.Deployment(name,
|
|
|
|
{
|
|
|
|
metadata: {
|
|
|
|
namespace: config.appsNamespaceName,
|
|
|
|
labels: {app: name},
|
|
|
|
},
|
|
|
|
spec: {
|
|
|
|
replicas: 1,
|
|
|
|
selector: { matchLabels: labels },
|
|
|
|
template: {
|
|
|
|
metadata: { labels: labels, },
|
|
|
|
spec: {
|
|
|
|
containers: [
|
|
|
|
{
|
|
|
|
name: name,
|
|
|
|
image: "gcr.io/kuar-demo/kuard-amd64:blue",
|
|
|
|
resources: {requests: {cpu: "50m", memory: "20Mi"}},
|
|
|
|
ports: [{ name: "http", containerPort: 8080 }]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{provider: provider}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Create a Service for the kuard Deployment
|
|
|
|
const service = new k8s.core.v1.Service(name,
|
|
|
|
{
|
|
|
|
metadata: {labels: labels, namespace: config.appsNamespaceName},
|
|
|
|
spec: {ports: [{ port: 8080, targetPort: "http" }], selector: labels},
|
|
|
|
},
|
|
|
|
{provider: provider}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Export the Service name and public LoadBalancer endpoint
|
|
|
|
export const serviceName = service.metadata.name;
|
|
|
|
|
|
|
|
// Create the kuard Ingress
|
|
|
|
const ingress = new k8s.extensions.v1beta1.Ingress(name,
|
|
|
|
{
|
|
|
|
metadata: {
|
|
|
|
labels: labels,
|
|
|
|
namespace: config.appsNamespaceName,
|
|
|
|
annotations: {"kubernetes.io/ingress.class": "nginx"},
|
|
|
|
},
|
|
|
|
spec: {
|
|
|
|
rules: [
|
|
|
|
{
|
|
|
|
host: "apps.example.com",
|
|
|
|
http: {
|
|
|
|
paths: [
|
|
|
|
{
|
|
|
|
path: "/",
|
|
|
|
backend: {
|
|
|
|
serviceName: serviceName,
|
|
|
|
servicePort: "http",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{provider: provider}
|
|
|
|
);
|
|
|
|
```
|
|
|
|
|
|
|
|
Check that the ingress is created, and after a few moments the `Address` will
|
|
|
|
be set to the NGINX LoadBalancer Service address.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ kubectl describe ingress kuard-<POD_SUFFIX> --namespace=`pulumi stack output appsNamespaceName`
|
|
|
|
```
|
2019-12-18 09:59:20 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
|
|
|
|
|
|
|
{{< /chooser >}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
Use the NGINX LoadBalancer Service address to access kuard on its expected
|
|
|
|
hosts & paths. We simulate the headers using `curl`.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ curl -Lv -H 'Host: apps.example.com' <INGRESS_ADDRESS>
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Clean Up
|
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{< chooser k8s-language "typescript,yaml" >}}
|
|
|
|
|
|
|
|
{{% choosable k8s-language yaml %}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
2019-11-04 17:48:44 -08:00
|
|
|
Delete the pod, service, and ingress controller.
|
|
|
|
|
2019-10-25 18:53:40 -07:00
|
|
|
```bash
|
|
|
|
$ kubectl delete pod/kuard svc/kuard ingress/kuard
|
2020-06-23 13:37:13 -07:00
|
|
|
$ kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/cloud-generic.yaml
|
2019-10-25 18:53:40 -07:00
|
|
|
```
|
2019-12-18 09:59:20 -08:00
|
|
|
|
2020-03-20 09:32:19 -07:00
|
|
|
{{% /choosable %}}
|
|
|
|
|
|
|
|
{{% choosable k8s-language typescript %}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
|
|
|
Delete the nginx definition in the Pulumi program, and run a Pulumi update.
|
2020-03-20 09:32:19 -07:00
|
|
|
|
|
|
|
{{% /choosable %}}
|
|
|
|
|
|
|
|
{{< /chooser >}}
|
2019-10-25 18:53:40 -07:00
|
|
|
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-disable url -->
|
2019-10-25 18:53:40 -07:00
|
|
|
[k8s-kuard]: https://github.com/kubernetes-up-and-running/kuard
|
|
|
|
[k8s-ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
2019-12-18 09:59:20 -08:00
|
|
|
<!-- markdownlint-enable url -->
|