Published: Apr 11, 2024 by Isaac Johnson
Today I wanted to checkout a couple Open-Source app’s that have been on my list for a while.
Movary is a very small clean app for sharing movie reviews and watchlists. It can pull data from TMDB easily. While it’s documented to run in Docker, we’ll set it up in Kubernetes.
Moodist is a very small but functional background sound generator similar to Noisedash. We’ll launch that in Kubernetes as well.
Movary
As mentioned, Movary is a movie tracking app for sharing the movies one has seen.
The standard install leverages docker.
Let’s see if we can convert that Docker Compose over to a Kubernetes Manifest
version: "3.5"
services:
movary:
image: leepeuker/movary:latest
container_name: movary
ports:
- "80:80"
environment:
TMDB_API_KEY: "<tmdb_key>"
DATABASE_MODE: "mysql"
DATABASE_MYSQL_HOST: "mysql"
DATABASE_MYSQL_NAME: "movary"
DATABASE_MYSQL_USER: "movary_user"
DATABASE_MYSQL_PASSWORD: "movary_password"
volumes:
- movary-storage:/app/storage
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: "movary"
MYSQL_USER: "movary_user"
MYSQL_PASSWORD: "movary_password"
MYSQL_ROOT_PASSWORD: "<mysql_root_password>"
volumes:
- movary-db:/var/lib/mysql
volumes:
movary-db:
movary-storage:
The volumes should turn into PVCs and the rest should be deployments
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: movary-db-pvc
spec:
storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: movary-storage-pvc
spec:
storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: movary-deployment
spec:
replicas: 1
selector:
matchLabels:
app: movary
template:
metadata:
labels:
app: movary
spec:
containers:
- name: movary
image: leepeuker/movary:latest
ports:
- containerPort: 80
env:
- name: TMDB_API_KEY
value: "171b839b39e603744dafc276a33b70e"
- name: DATABASE_MODE
value: "mysql"
- name: DATABASE_MYSQL_HOST
value: "movary-mysql"
- name: DATABASE_MYSQL_NAME
value: "movary"
- name: DATABASE_MYSQL_USER
value: "movary_user"
- name: DATABASE_MYSQL_PASSWORD
value: "movary_password"
volumeMounts:
- name: movary-storage
mountPath: /app/storage
volumes:
- name: movary-storage
persistentVolumeClaim:
claimName: movary-storage-pvc
---
apiVersion: v1
kind: Service
metadata:
name: movary-service
spec:
selector:
app: movary
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: movary-mysql
spec:
replicas: 1
selector:
matchLabels:
app: movary-mysql
template:
metadata:
labels:
app: movary-mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_DATABASE
value: "movary"
- name: MYSQL_USER
value: "movary_user"
- name: MYSQL_PASSWORD
value: "movary_password"
- name: MYSQL_ROOT_PASSWORD
value: "movary_password"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: movary-db-pvc
---
apiVersion: v1
kind: Service
metadata:
name: movary-mysql
spec:
selector:
app: movary-mysql
ports:
- protocol: TCP
port: 3306
targetPort: 3306
type: ClusterIP
You can get an API key for TMDB from here.
I’ll then create a namespace and apply the manifest
$ kubectl create ns movary
namespace/movary created
$ kubectl apply -f manifest.yaml -n movary
persistentvolumeclaim/movary-db-pvc created
persistentvolumeclaim/movary-storage-pvc created
deployment.apps/movary-deployment created
service/movary-service created
deployment.apps/movary-mysql created
service/movary-mysql created
It seemed to start right away
$ kubectl get svc -n movary
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
movary-service ClusterIP 10.43.106.44 <none> 80/TCP 4s
movary-mysql ClusterIP 10.43.49.104 <none> 3306/TCP 4s
$ kubectl get pods -n movary
NAME READY STATUS RESTARTS AGE
movary-deployment-59bc965c6c-6rtqb 1/1 Running 0 39s
movary-mysql-745cbd96b4-n97jv 1/1 Running 0 39s
A quick port-forward didn’t work too hot
$ kubectl port-forward svc/movary-service -n movary 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
E0403 07:47:32.102960 23618 portforward.go:381] error copying from remote stream to local connection: readfrom tcp6 [::1]:8888->[::1]:46910: write tcp6 [::1]:8888->[::1]:46910: write: broken pipe
E0403 07:47:32.109495 23618 portforward.go:381] error copying from remote stream to local connection: readfrom tcp6 [::1]:8888->[::1]:46886: write tcp6 [::1]:8888->[::1]:46886: write: broken pipe
I can see plenty of errors in the logs
$ kubectl logs movary-deployment-59bc965c6c-hjzvc -n movary | tail -n10
127.0.0.1 - - [03/Apr/2024:12:47:42 +0000] "GET /serviceWorker.js HTTP/1.1" 304 0 "http://localhost:8888/serviceWorker.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
[2024-04-03T14:47:44.130009+02:00] movary.EMERGENCY: An exception occurred while executing a query: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist {"exception":"[object] (Doctrine\\DBAL\\Exception\\TableNotFoundException(code: 1146): An exception occurred while executing a query: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist at /app/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php:49)\n[previous exception] [object] (Doctrine\\DBAL\\Driver\\PDO\\Exception(code: 1146): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist at /app/vendor/doctrine/dbal/src/Driver/PDO/Exception.php:28)\n[previous exception] [object] (PDOException(code: 42S02): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist at /app/vendor/doctrine/dbal/src/Driver/PDO/Connection.php:71)"} []
[php-fpm:access] 127.0.0.1 - 03/Apr/2024:12:47:44 +0000 "GET /index.php" 500 /app/public/index.php 14.818 2048 67.49%
127.0.0.1 - - [03/Apr/2024:12:47:44 +0000] "GET / HTTP/1.1" 500 3394 "http://localhost:8888/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
[2024-04-03T14:47:45.225421+02:00] movary.EMERGENCY: An exception occurred while executing a query: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist {"exception":"[object] (Doctrine\\DBAL\\Exception\\TableNotFoundException(code: 1146): An exception occurred while executing a query: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist at /app/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php:49)\n[previous exception] [object] (Doctrine\\DBAL\\Driver\\PDO\\Exception(code: 1146): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist at /app/vendor/doctrine/dbal/src/Driver/PDO/Exception.php:28)\n[previous exception] [object] (PDOException(code: 42S02): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'movary.user' doesn't exist at /app/vendor/doctrine/dbal/src/Driver/PDO/Connection.php:71)"} []
[php-fpm:access] 127.0.0.1 - 03/Apr/2024:12:47:45 +0000 "GET /index.php" 500 /app/public/index.php 19.678 2048 50.82%
127.0.0.1 - - [03/Apr/2024:12:47:45 +0000] "GET / HTTP/1.1" 500 3394 "http://localhost:8888/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
127.0.0.1 - - [03/Apr/2024:12:47:46 +0000] "GET /serviceWorker.js HTTP/1.1" 304 0 "http://localhost:8888/serviceWorker.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
127.0.0.1 - - [03/Apr/2024:12:47:47 +0000] "GET /serviceWorker.js HTTP/1.1" 304 0 "http://localhost:8888/serviceWorker.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
127.0.0.1 - - [03/Apr/2024:12:48:05 +0000] "GET /serviceWorker.js HTTP/1.1" 304 0 "http://localhost:8888/serviceWorker.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
Rechecking the docs, we can see there is a manual DB Migrate one is expected to perform:
I can do the equivalent by exec’ing into the app pod in Kubernetes and running the command
$ kubectl exec -it movary-deployment-59bc965c6c-hjzvc -n movary -- /bin/bash
movary-deployment-59bc965c6c-hjzvc:/app$ php bin/console.php database:migration:migrate
using config file settings/phinx.php
using config parser php
using migration paths
- /app/db/migrations/mysql
warning no environment specified, defaulting to: dynamic
using adapter mysql
using database movary
ordering by creation time
== 20210124104021 SetupBaseTables: migrating
== 20210124104021 SetupBaseTables: migrated 0.0864s
== 20210204195525 AddMoreMovieDetails: migrating
== 20210204195525 AddMoreMovieDetails: migrated 0.1641s
== 20210204211239 RemoveYearFromMovie: migrating
== 20210204211239 RemoveYearFromMovie: migrated 0.0296s
== 20210206222052 AddGenre: migrating
== 20210206222052 AddGenre: migrated 0.0606s
== 20220402194534 AddPerson: migrating
== 20220402194534 AddPerson: migrated 0.0823s
== 20220418073143 AddProductionCompanies: migrating
== 20220418073143 AddProductionCompanies: migrated 0.0559s
== 20220418081407 AddMovieTagline: migrating
== 20220418081407 AddMovieTagline: migrated 0.0389s
== 20220420173442 AddSecondRatingType: migrating
== 20220420173442 AddSecondRatingType: migrated 0.0648s
== 20220420185953 AddLetterboxdId: migrating
== 20220420185953 AddLetterboxdId: migrated 0.0428s
== 20220424171847 RemoveTimeFromWatchDate: migrating
== 20220424171847 RemoveTimeFromWatchDate: migrated 0.0483s
== 20220505182414 AddPosterPathToMovie: migrating
== 20220505182414 AddPosterPathToMovie: migrated 0.0432s
== 20220506184030 AddSyncLogTable: migrating
== 20220506184030 AddSyncLogTable: migrated 0.0218s
== 20220506195137 ChangePrimaryKeyInTraktCache: migrating
== 20220506195137 ChangePrimaryKeyInTraktCache: migrated 0.0398s
== 20220510185016 AddUser: migrating
== 20220510185016 AddUser: migrated 0.0277s
== 20220514093905 AddPlaysToHistory: migrating
== 20220514093905 AddPlaysToHistory: migrated 0.0494s
== 20220515085154 AddPosterPathToPerson: migrating
== 20220515085154 AddPosterPathToPerson: migrated 0.0321s
== 20220604103136 SplitUpMovePosterPath: migrating
== 20220604103136 SplitUpMovePosterPath: migrated 0.1113s
== 20220605074031 ChangeMovieTraktIdAndImdbIdToNullable: migrating
== 20220605074031 ChangeMovieTraktIdAndImdbIdToNullable: migrated 0.1028s
== 20220606175053 ChangeTraktIdToUniqueInWatchedCache: migrating
== 20220606175053 ChangeTraktIdToUniqueInWatchedCache: migrated 0.0555s
== 20220624095147 ReplaceRating10AndRating5WithPersonalRating: migrating
== 20220624095147 ReplaceRating10AndRating5WithPersonalRating: migrated 0.0676s
== 20220628192946 AddPlexWebhookId: migrating
== 20220628192946 AddPlexWebhookId: migrated 0.0189s
== 20220630135944 AddUserAuthTokenTable: migrating
== 20220630135944 AddUserAuthTokenTable: migrated 0.0246s
== 20220708144310 AddMultiUserSetup: migrating
== 20220708144310 AddMultiUserSetup: migrated 0.3478s
== 20220711194814 SetCorrectConstraintForMovieWatchDates: migrating
== 20220711194814 SetCorrectConstraintForMovieWatchDates: migrated 0.0301s
== 20220713163724 AddTraktClientIdToUserTable: migrating
== 20220713163724 AddTraktClientIdToUserTable: migrated 0.0569s
== 20220714094745 AddCacheTableForTmdbLanguages: migrating
== 20220714094745 AddCacheTableForTmdbLanguages: migrated 0.0196s
== 20220714115426 AddDateFormatToUserTable: migrating
== 20220714115426 AddDateFormatToUserTable: migrated 0.0320s
== 20220718170243 AddCoreAccountChangesDisabledToUser: migrating
== 20220718170243 AddCoreAccountChangesDisabledToUser: migrated 0.0313s
== 20220719134322 AddJobQueueTable: migrating
== 20220719134322 AddJobQueueTable: migrated 0.0196s
== 20220725113013 UpdateUsername: migrating
== 20220725113013 UpdateUsername: migrated 0.0500s
== 20220728103556 AddPrivacyLevelToUser: migrating
== 20220728103556 AddPrivacyLevelToUser: migrated 0.0294s
== 20220731091237 AddImdbRatingToMovie: migrating
== 20220731091237 AddImdbRatingToMovie: migrated 0.1745s
== 20220804080839 UpdateProductionCompanyForeignKeys: migrating
== 20220804080839 UpdateProductionCompanyForeignKeys: migrated 0.1080s
== 20220815113051 UpdateJobQueueTable: migrating
== 20220815113051 UpdateJobQueueTable: migrated 0.0325s
== 20220816164829 RemoveScanLog: migrating
== 20220816164829 RemoveScanLog: migrated 0.0128s
== 20221206190149 ExtendPersonMetaData: migrating
== 20221206190149 ExtendPersonMetaData: migrated 0.0787s
== 20221208101424 AddPlexScrobbleOptionsToUser: migrating
== 20221208101424 AddPlexScrobbleOptionsToUser: migrated 0.0558s
== 20221209195438 UpdateMoveForeignKeysToCascade: migrating
== 20221209195438 UpdateMoveForeignKeysToCascade: migrated 0.2059s
== 20221220113521 InitialSqliteAdjustment: migrating
== 20221220113521 InitialSqliteAdjustment: migrated 0.2649s
== 20221225093745 SetCastCharacterNameColumnToNullable: migrating
== 20221225093745 SetCastCharacterNameColumnToNullable: migrated 0.0306s
== 20221230153943 AddLetterboxdDiaryCacheTable: migrating
== 20221230153943 AddLetterboxdDiaryCacheTable: migrated 0.0173s
== 20230103172838 AddJellyfinWebhookId: migrating
== 20230103172838 AddJellyfinWebhookId: migrated 0.0569s
== 20230127104327 AddBackdropPathToMovieTable: migrating
== 20230127104327 AddBackdropPathToMovieTable: migrated 0.0357s
== 20230128101746 AddCommentToWatchDate: migrating
== 20230128101746 AddCommentToWatchDate: migrated 0.0261s
== 20230410104922 AddIsAdminToUserTable: migrating
== 20230410104922 AddIsAdminToUserTable: migrated 0.0408s
== 20230417183901 AddWatchlistTable: migrating
== 20230417183901 AddWatchlistTable: migrated 0.0352s
== 20230423165919 AddServerSettingTable: migrating
== 20230423165919 AddServerSettingTable: migrated 0.0179s
== 20230506194733 AddWatchlistAutomaticRemovalEnabledColumnToUserTable: migrating
== 20230506194733 AddWatchlistAutomaticRemovalEnabledColumnToUserTable: migrated 0.0384s
== 20230507095753 AddEmbyWebhookIdToUserTable: migrating
== 20230507095753 AddEmbyWebhookIdToUserTable: migrated 0.0824s
== 20230507185125 AddDashboardSettingsToUserTable: migrating
== 20230507185125 AddDashboardSettingsToUserTable: migrated 0.1016s
== 20230627162519 AddPlexOAuthColumnsToUserTable: migrating
== 20230627162519 AddPlexOAuthColumnsToUserTable: migrated 0.1780s
== 20230704133329 AddBiographyToPersonTable: migrating
== 20230704133329 AddBiographyToPersonTable: migrated 0.0256s
== 20230714115544 CreateTmdbIsoCountryCacheTable: migrating
== 20230714115544 CreateTmdbIsoCountryCacheTable: migrated 0.0203s
== 20230716185217 AddCountryColumnToUserTable: migrating
== 20230716185217 AddCountryColumnToUserTable: migrated 0.0672s
== 20230727132752 AddJellyfinAccessTokenColumn: migrating
== 20230727132752 AddJellyfinAccessTokenColumn: migrated 0.1107s
== 20230801150607 AddJellyfinSyncEnabledToUserTable: migrating
== 20230801150607 AddJellyfinSyncEnabledToUserTable: migrated 0.0639s
== 20230814190244 AddTotpSecretColumn: migrating
== 20230814190244 AddTotpSecretColumn: migrated 0.0395s
== 20230902112622 AddUserApiTokenTable: migrating
== 20230902112622 AddUserApiTokenTable: migrated 0.0270s
== 20230908191445 AddRadarrFeedUuidColumnToUserTable: migrating
== 20230908191445 AddRadarrFeedUuidColumnToUserTable: migrated 0.0475s
== 20230911074701 SetWatchDateNullableForUsers: migrating
== 20230911074701 SetWatchDateNullableForUsers: migrated 0.0869s
== 20230929140932 RemoveUniqueNameAndCountryConstraintForCompany: migrating
== 20230929140932 RemoveUniqueNameAndCountryConstraintForCompany: migrated 0.0201s
== 20231001110211 AddImdbIdToPersonTable: migrating
== 20231001110211 AddImdbIdToPersonTable: migrated 0.0324s
== 20231006174123 CreateUserPersonSettingsTable: migrating
== 20231006174123 CreateUserPersonSettingsTable: migrated 0.0335s
== 20231007144149 AddDisplayCharacterNamesToUserTable: migrating
== 20231007144149 AddDisplayCharacterNamesToUserTable: migrated 0.0530s
== 20231112151603 AddPositionToUserWatchDatesTable: migrating
== 20231112151603 AddPositionToUserWatchDatesTable: migrated 0.0220s
All Done. Took 4.2013s
That fixed it
Once my initial user was created, I could see the app
Though trying to get to settings showed the error page and i got errors trying to add a movie
That error showed in the logs
[php-fpm:access] 127.0.0.1 - 03/Apr/2024:13:04:22 +0000 "POST /index.php" 500 /app/public/index.php 199.105 2048 35.16%
127.0.0.1 - - [03/Apr/2024:13:04:22 +0000] "POST /settings/netflix/search HTTP/1.1" 500 11478 "http://localhost:8888/users/idjohnson/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
[2024-04-03T15:04:25.632165+02:00] movary.EMERGENCY: TMDB API key is probably not set or invalid. {"exception":"[object] (Movary\\Api\\Tmdb\\Exception\\TmdbAuthorizationError(code: 0): TMDB API key is probably not set or invalid. at /app/src/Api/Tmdb/Exception/TmdbAuthorizationError.php:11)"} []
That I didn’t have a proper key and indeed I had made a typo in the TMDB API Key field.
I fixed the API and applied. Now the movie add dialogue worked
I added some movies I’ve seen and want to see
$ kubectl port-forward svc/movary-service -n movary 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
Handling connection for 8888
Handling connection for 8888
This looks good. I think it’s time to expose externally.
I’ll add an A Record
$ cat r53-movary.json
{
"Comment": "CREATE movary fb.s A record ",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "movary.freshbrewed.science",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{
"Value": "75.73.224.240"
}
]
}
}
]
}
$ aws route53 change-resource-record-sets --hosted-zone-id Z39E8QFU0F9PZP --change-batch file://r53-movary.json
{
"ChangeInfo": {
"Id": "/change/C05540171355MASD8TPK2",
"Status": "PENDING",
"SubmittedAt": "2024-04-03T21:11:06.233Z",
"Comment": "CREATE movary fb.s A record "
}
}
And then create an Ingress
builder@DESKTOP-QADGF36:~/Workspaces/jekyll-blog$ cat movary.ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
ingress.kubernetes.io/proxy-body-size: "0"
ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.org/client-max-body-size: "0"
nginx.org/proxy-connect-timeout: "3600"
nginx.org/proxy-read-timeout: "3600"
labels:
app.kubernetes.io/instance: movary
name: movaryingress
namespace: movary
spec:
rules:
- host: movary.freshbrewed.science
http:
paths:
- backend:
service:
name: movary-service
port:
number: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- movary.freshbrewed.science
secretName: movary-tls
builder@DESKTOP-QADGF36:~/Workspaces/jekyll-blog$ kubectl apply -f ./movary.ingress.yaml -n movary
ingress.networking.k8s.io/movaryingress created
Interesting, now that it has a proper DNS, the settings page seems to work
I can setup Email now under settings
which is easy enough to test
Which I soon received
I can also add a guest account
Feel free to give it a try with guest@guest.com / guestoffreshbrewed
Sharing
I only realized this later; you can share publicly your reviews.
You have to set the visibility in settings
Then you can publish a URL like https://movary.freshbrewed.science/users/idjohnson/dashboard which shows my current movies and reviews
Moodist
We reviewed Noisedash a while back. Let’s look at another noise app, Moodist
Let’s create a Kubernetes manifest
$ cat manifest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: moodist-deployment
spec:
replicas: 1
selector:
matchLabels:
app: moodist
template:
metadata:
labels:
app: moodist
spec:
containers:
- name: moodist
image: ghcr.io/remvze/moodist
resources:
limits:
memory: 4Gi
cpu: 200m
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
ports:
- containerPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: moodist-service
spec:
selector:
app: moodist
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
Since we used AWS Route53 last time, let’s use Azure DNS for this app
$ az account set --subscription "Pay-As-You-Go" && az network dns record-set a add-record -g idjdnsrg -z tpk.pw -a 75.73.224.240 -n moodist
{
"ARecords": [
{
"ipv4Address": "75.73.224.240"
}
],
"TTL": 3600,
"etag": "e9e527f7-3db7-4d02-8358-a75ec42ee7de",
"fqdn": "moodist.tpk.pw.",
"id": "/subscriptions/d955c0ba-13dc-44cf-a29a-8fed74cbb22d/resourceGroups/idjdnsrg/providers/Microsoft.Network/dnszones/tpk.pw/A/moodist",
"name": "moodist",
"provisioningState": "Succeeded",
"resourceGroup": "idjdnsrg",
"targetResource": {},
"trafficManagementProfile": {},
"type": "Microsoft.Network/dnszones/A"
}
I can now create an Ingress that uses my AzureDNS cluster issuer
$ cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: azuredns-tpkpw
ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.org/websocket-services: moodist-service
name: moodist-ingress
spec:
rules:
- host: moodist.tpk.pw
http:
paths:
- backend:
service:
name: moodist-service
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- moodist.tpk.pw
secretName: moodist-tls
And apply it
$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/moodist-ingress created
Since I was in a loud area, I tested using my phone
Frankly that sounded a lot like a campsite in the BWCA. I really got (am) relaxed.
I found airplane and brown noise was another good one. Though I generally just fire up this YouTube for Airplane Noise. The thing is i can hear a slight high pitch repeat on the app’s airplane noise and once I notice, it’s hard to un-notice.
Still, you are welcome to try https://moodist.tpk.pw/.
Summary
I wanted to share a couple apps that were on my radar, Moodist and Movery. Movary is a pretty nifty catalogue for tracking your movies and reviews.
Both can run quite easily in Docker but moving to Kubernetes let us handle TLS and route with DNS names.