diff --git a/k8s/portworx.yaml b/k8s/portworx.yaml
index 4a196441..c3e21d0a 100644
--- a/k8s/portworx.yaml
+++ b/k8s/portworx.yaml
@@ -1,5 +1,4 @@
# SOURCE: https://install.portworx.com/?kbver=1.15.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true&st=k8s&mc=false
-# SOURCE: https://install.portworx.com/?kbver=1.15.2&b=true&s=/dev/loop4&c=px-workshop&stork=true&lh=true&st=k8s&mc=false
---
kind: Service
apiVersion: v1
@@ -751,3 +750,16 @@ spec:
volumes:
- name: config
emptyDir: {}
+---
+# That one is an extra.
+# Create a default Storage Class to simplify Portworx setup.
+kind: StorageClass
+apiVersion: storage.k8s.io/v1beta1
+metadata:
+ name: portworx-replicated
+ annotations:
+ storageclass.kubernetes.io/is-default-class: "true"
+provisioner: kubernetes.io/portworx-volume
+parameters:
+ repl: "2"
+ priority_io: "high"
diff --git a/k8s/postgres.yaml b/k8s/postgres.yaml
index 75ac4b8e..a9331f2a 100644
--- a/k8s/postgres.yaml
+++ b/k8s/postgres.yaml
@@ -12,7 +12,14 @@ spec:
labels:
app: postgres
spec:
- schedulerName: stork
+ #schedulerName: stork
+ initContainers:
+ - name: rmdir
+ image: alpine
+ volumeMounts:
+ - mountPath: /vol
+ name: postgres
+ command: ["sh", "-c", "if [ -d /vol/lost+found ]; then rmdir /vol/lost+found; fi"]
containers:
- name: postgres
image: postgres:11
diff --git a/prepare-vms/lib/commands.sh b/prepare-vms/lib/commands.sh
index ade36b6e..68904fa5 100644
--- a/prepare-vms/lib/commands.sh
+++ b/prepare-vms/lib/commands.sh
@@ -362,6 +362,16 @@ _cmd_opensg() {
infra_opensg
}
+_cmd portworx "Prepare the nodes for Portworx deployment"
+_cmd_portworx() {
+ TAG=$1
+ need_tag
+
+ pssh "
+ sudo truncate --size 10G /portworx.blk &&
+ sudo losetup /dev/loop4 /portworx.blk"
+}
+
_cmd disableaddrchecks "Disable source/destination IP address checks"
_cmd_disableaddrchecks() {
TAG=$1
diff --git a/slides/k8s/kubectlexpose.md b/slides/k8s/kubectlexpose.md
index 0e6c5ecd..e6cc8f03 100644
--- a/slides/k8s/kubectlexpose.md
+++ b/slides/k8s/kubectlexpose.md
@@ -14,42 +14,80 @@
`ClusterIP`, `NodePort`, `LoadBalancer`, `ExternalName`
----
-
-## Basic service types
-
-- `ClusterIP` (default type)
-
- - a virtual IP address is allocated for the service (in an internal, private range)
- - this IP address is reachable only from within the cluster (nodes and pods)
- - our code can connect to the service using the original port number
-
-- `NodePort`
-
- - a port is allocated for the service (by default, in the 30000-32768 range)
- - that port is made available *on all our nodes* and anybody can connect to it
- - our code must be changed to connect to that new port number
-
-These service types are always available.
-
-Under the hood: `kube-proxy` is using a userland proxy and a bunch of `iptables` rules.
+- HTTP services can also use `Ingress` resources (more on that later)
---
-## More service types
+## `ClusterIP`
-- `LoadBalancer`
+- It's the default service type
- - an external load balancer is allocated for the service
- - the load balancer is configured accordingly
-
(e.g.: a `NodePort` service is created, and the load balancer sends traffic to that port)
- - available only when the underlying infrastructure provides some "load balancer as a service"
-
(e.g. AWS, Azure, GCE, OpenStack...)
+- A virtual IP address is allocated for the service
-- `ExternalName`
+ (in an internal, private range; e.g. 10.96.0.0/12)
- - the DNS entry managed by CoreDNS will just be a `CNAME` to a provided record
- - no port, no IP address, no nothing else is allocated
+- This IP address is reachable only from within the cluster (nodes and pods)
+
+- Our code can connect to the service using the original port number
+
+- Perfect for internal communication, within the cluster
+
+---
+
+## `LoadBalancer`
+
+- An external load balancer is allocated for the service
+
+ (typically a cloud load balancer, e.g. ELB on AWS, GLB on GCE ...)
+
+- This is available only when the underlying infrastructure provides some kind of
+ "load balancer as a service"
+
+- Each service of that type will typically cost a little bit of money
+
+ (e.g. a few cents per hour on AWS or GCE)
+
+- Ideally, traffic would flow directly from the load balancer to the pods
+
+- In practice, it will often flow through a `NodePort` first
+
+---
+
+## `NodePort`
+
+- A port number is allocated for the service
+
+ (by default, in the 30000-32768 range)
+
+- That port is made available *on all our nodes* and anybody can connect to it
+
+ (we can connect to any node on that port to reach the service)
+
+- Our code needs to be changed to connect to that new port number
+
+- Under the hood: `kube-proxy` sets up a bunch of `iptables` rules on our nodes
+
+- Sometimes, it's the only available option for external traffic
+
+ (e.g. most clusters deployed with kubeadm or on-premises)
+
+---
+
+class: extra-details
+
+## `ExternalName`
+
+- No load balancer (internal or external) is created
+
+- Only a DNS entry gets added to the DNS managed by Kubernetes
+
+- That DNS entry will just be a `CNAME` to a provided record
+
+Example:
+```bash
+kubectl create service externalname k8s --external-name kubernetes.io
+```
+*Creates a CNAME `k8s` pointing to `kubernetes.io`*
---
@@ -279,18 +317,28 @@ error: the server doesn't have a resource type "endpoint"
---
-## Exposing services to the outside world
+class: extra-details
-- The default type (ClusterIP) only works for internal traffic
+## `ExternalIP`
-- If we want to accept external traffic, we can use one of these:
+- When creating a servivce, we can also specify an `ExternalIP`
- - NodePort (expose a service on a TCP port between 30000-32768)
+ (this is not a type, but an extra attribute to the service)
- - LoadBalancer (provision a cloud load balancer for our service)
+- It will make the service availableon this IP address
- - ExternalIP (use one node's external IP address)
+ (if the IP address belongs to a node of the cluster)
- - Ingress (a special mechanism for HTTP services)
+---
-*We'll see NodePorts and Ingresses more in detail later.*
+## `Ingress`
+
+- Ingresses are another type (kind) of resource
+
+- They are specifically for HTTP services
+
+ (not TCP or UDP)
+
+- They can also handle TLS certificates, URL rewriting ...
+
+- They require an *Ingress Controller* to function
diff --git a/slides/k8s/portworx.md b/slides/k8s/portworx.md
index a78a5d24..ac0b7abd 100644
--- a/slides/k8s/portworx.md
+++ b/slides/k8s/portworx.md
@@ -240,6 +240,25 @@ If you want to use an external key/value store, add one of the following:
---
+## Check our default Storage Class
+
+- The YAML manifest applied earlier should define a default storage class
+
+.exercise[
+
+- Check that we have a default storage class:
+ ```bash
+ kubectl get storageclass
+ ```
+
+]
+
+There should be a storage class showing as `portworx-replicated (default)`.
+
+---
+
+class: extra-details
+
## Our default Storage Class
This is our Storage Class (in `k8s/storage-class.yaml`):
@@ -265,28 +284,6 @@ parameters:
---
-## Creating our Storage Class
-
-- Let's apply that YAML file!
-
-.exercise[
-
-- Create the Storage Class:
- ```bash
- kubectl apply -f ~/container.training/k8s/storage-class.yaml
- ```
-
-- Check that it is now available:
- ```bash
- kubectl get sc
- ```
-
-]
-
-It should show as `portworx-replicated (default)`.
-
----
-
## Our Postgres Stateful set
- The next slide shows `k8s/postgres.yaml`
@@ -326,7 +323,7 @@ spec:
schedulerName: stork
containers:
- name: postgres
- image: postgres:10.5
+ image: postgres:11
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres