Всем привет! В преддверии старта курса «Инфраструктурная платформа на основе Kubernetes» подготовили перевод еще одного интересного материала.
Эта статья рассчитана на новичков в Kubernetes, которым будет интересно разобраться на практическом примере, как написать Golang API для управления TODO list-ом, и затем как развернуть его в Kubernetes.
Каждый разработчик любит хороший TODO list, не правда ли? Как бы еще мы могли себя организовать иначе?
Каждый разработчик любит хорошее TODO приложение, не так ли?
Мы начнем с обзора перечня необходимых компонентов, затем перейдем к настройке Kubernetes, предоставим базу данных Postgresql, а затем установим фреймворк приложения, который поможет нам легко развернуть Go API в Kubernetes, не зацикливаясь на деталях.
Мы создадим два эндпоинта в API — один для создания новой TODO записи, другой для выбора всех TODO записей.
Весь код из этого туториала доступен на GitHub
Kubernetes запускает код в образах контейнеров, поэтому вам необходимо установить Docker на свой компьютер.
Установите Docker: https://www.docker.com
Зарегистрируйте учетную запись Docker Hub для хранения ваших образов Docker: https://hub.docker.com/
Вы можете выбрать либо локальный, либо удаленный кластер, но какой лучше? Упрощенные варианты, такие как k3d, работают на любом компьютере, на котором может работать Docker, поэтому для запуска локального кластера больше не требуется много оперативной памяти. Удаленный кластер также может быть очень эффективным решением, но имейте в виду, что все ваши образы Docker нужно будет выгружать и загружать для каждого изменения.
Установите k3d: https://github.com/rancher/k3d
k3d не установит kubectl (это CLI для Kubernetes), поэтому установите его отдельно отсюда: https://kubernetes.io/docs/tasks/tools / install-kubectl
Так же вам необходимо установить на ваш компьютер Golang вместе с IDE. Go бесплатен, и вы можете скачать его для MacOS, Windows или Linux по следующей ссылке: https://golang.org/dl
Я бы порекомендовал использовать Visual Studio Code, она бесплатно и имеет набор плагинов для Go, которые вы можете добавить. Некоторые коллеги предпочитают Goland от Jetbrains. Если вы Java программист, вы, вероятно, предпочтете заплатить за Goland, поскольку он будет напоминать вам о других их продуктах.
Установите VSCode или Golang.
Вам необходимо установить все программное обеспечение, указанное в предыдущем разделе.
Настройте kubectl таким образом, чтобы он указывал на новый кластер. Помните, что с одного компьютера могут использоваться несколько кластеров, поэтому крайне важно указывать на правильный:
Убедитесь, что в кластере есть хотя бы один узел. Здесь вы можете видеть, что у меня установлен Kubernetes 1.17 — относительно новая версия:
Мы будем хранить наши TODO записи в таблице базы данных, поэтому теперь нам нужно ее установить. Postgresql — это популярная реляционная база данных, которую мы можем установить в кластер с помощью диаграммы Хелма.
arkade — это CLI Go, похожий на «brew» или «apt-get», но для приложений Kubernetes. Он использует Helm, kubectl или CLI проекта для установки проекта или продукта в ваш кластер.
Теперь установите Postgresql
Вы также увидите информацию о строке подключения и о том, как запустить CLI Postgresql через образ Docker внутри кластера.
Вы можете получить эту информацию в любое время с помощью
Спроектируем схему таблицы
Запустите
Теперь у вас в командной строке есть:
Так же, как PHP разработчики ускорили свой рабочий процесс с помощью LAMP (Linux Apache + Mysql + PHP) и Rails разработчики с помощью предварительно подготовленного стека, разработчики Kubernetes могут использовать фреймворки приложений.
Стек PLONK расшифровывается как Prometheus, Linux, OpenFaaS, NATS и Kubernetes.
Установите стек PLONK через arkade:
Прочитайте информационное сообщение и выполните каждую команду:
Как и раньше, вы можете получить информационное сообщение с помощью
Существует несколько способов создания API Go с помощью PLONK. Первый вариант — использовать Dockerfile и вручную определить TCP порт, проверку работоспособности, HTTP-сервер и так далее. Это можно сделать с помощью
Второй способ — воспользоваться встроенными шаблонами, предлагаемыми Function Store:
Поскольку мы хотим создать традиционный API в HTTP стиле, шаблон golang-middleware будет наиболее подходящим.
В начале туториала вы зарегистрировали в учетную запись Docker Hub для хранения ваших образов Docker. Каждая рабочая нагрузка в Kubernetes должна быть встроена в образ Docker, прежде чем ее можно будет развернуть.
Подтяните специальный шаблон:
Используйте Scaffold для вашего API с golang-middleware и вашим юзернеймом в Docker Hub:
Вы увидите два сгенерированных файла:
Давайте проведем небольшое редактирование и затем развернем код.
Если вы не используете VScode и его плагины для редактирования и форматирования кода, то запускайте это после каждого изменения, чтобы убедиться, что файл правильно отформатирован.
Теперь развернем код — сначала создадим новый образ, запушим его в Docker Hub и развернем в кластере с помощью OpenFaaS API:
Теперь разрешим пользователям создавать новые записи в своем TODO list-е. Сначала вам нужно добавить ссылку или «зависимость» для Go в библиотеку Postgresql.
Мы можем получить ее с помощью вендинга или модулей Go, которые были введены в Go 1.11 и установлены по умолчанию в Go 1.13.
Отредактируйте
Чтобы модули Go могли обнаружить зависимость, мы должны объявить кое-что внутри файла, который мы будем использовать позже. Если мы не сделаем этого, то VSCode удалит эти строки при сохранении.
Добавьте это под импортами в файле
Всегда запускайте эти команды в
Инициализируйте новый модуль Go:
Теперь обновите файл с помощью библиотеки pq:
Что бы ни было внутри
Теперь давайте убедимся, что сборка все еще работает до добавления кода insert.
Вы можете заметить, что теперь мы передаем
Во время сборки вы увидите, что модули загружаются по мере необходимости из интернета.
Мы можем создать пул соединений в
Как вы заметили, некоторая информация извлекается из
Остальные, такие как пароль и хост, которые являются конфиденциальными, хранятся в секретах Kubernetes.
Вы можете создать их через
Строка
Получим секретные значения из
Теперь для каждого пароля выполним следующее:
Проверим секреты на предмет наличия и соответствия:
Отредактируем наш YAML файл и добавим следующее:
Далее обновим модули Go и снова запустим сборку:
Сборка отработала как положено, поэтому запустим
Проверим журналы:
Пока все выглядит хорошо, теперь попробуем вызвать эндпоинт:
Итак, теперь у нас установлено успешное соединение с БД, и мы можем выполнять insert. Откуда мы это знаем? Потому что
Перейдите по ссылке для более подробной информации о пакете database/sql.
Этот код вставляет новую строку в таблицу
Представьте, что кто-то введет описание;
Поэтому мы запускаем
Теперь давайте подключим это к коду.
Давайте развернем это и запустим.
Проверим логи API:
Проверим содержимое таблицы с помощью pgsql:
Поздравляем, теперь у вас есть API TODO, которое может принимать входящие запросы через
Давайте создадим новую функцию для запроса TODO записей из таблицы:
Мы не можем назвать этот метод select, потому что это зарезервированное ключевое слово для работы с горутинами.
Теперь подключим метод к основному обработчику:
Теперь, когда в нашей схеме данных есть дополнительные поля для дат, обновите структуру Todo:
Теперь давайте добавим в наш метод
Как и раньше, нам нужно отложить закрытие строк для запроса. Каждое значение вставляется в новую структуру с помощью метода rows.Scan. В конце метода у нас есть кусочек содержимого Todo.
Попробуем:
Вот результат:
Чтобы удалить значения, мы можем обновить аннотации структуры, добавив
Мы еще не закончили, но это хороший момент, чтобы остановиться и пересмотреть то, чего мы достигли на данный момент. Мы:
Полный пример кода, который мы создали до сих пор, доступен на моем GitHub акаунте: alexellis/kubernetes-todo-go-app
Дальше мы можем сделать гораздо больше, например:
И многое другое. Мы также могли бы покопаться в стеке PLONK и развернуть дашборд Grafana, чтобы начать наблюдать за нашим API и понять, сколько ресурсов используется с дашбордом Kubernetes или сервером метрик (установленным с помощью
Узнайте больше об arkade: https://get-arkade.dev
Посетите семинар OpenFaaS, чтобы подробнее изучить вышесказанное: https://github.com/openfaas/workshop/
Вы можете подписаться на мою премиальную рассылку «Insiders Updates» на
https://www.alexellis.io/
и на мой твиттер Alex Ellis
Узнать подробнее о курсе
Эта статья рассчитана на новичков в Kubernetes, которым будет интересно разобраться на практическом примере, как написать Golang API для управления TODO list-ом, и затем как развернуть его в Kubernetes.
Каждый разработчик любит хороший TODO list, не правда ли? Как бы еще мы могли себя организовать иначе?
Каждый разработчик любит хорошее TODO приложение, не так ли?
Мы начнем с обзора перечня необходимых компонентов, затем перейдем к настройке Kubernetes, предоставим базу данных Postgresql, а затем установим фреймворк приложения, который поможет нам легко развернуть Go API в Kubernetes, не зацикливаясь на деталях.
Мы создадим два эндпоинта в API — один для создания новой TODO записи, другой для выбора всех TODO записей.
Весь код из этого туториала доступен на GitHub
Перечень необходимых компонентов:
- Локально установленный Docker
Kubernetes запускает код в образах контейнеров, поэтому вам необходимо установить Docker на свой компьютер.
Установите Docker: https://www.docker.com
Зарегистрируйте учетную запись Docker Hub для хранения ваших образов Docker: https://hub.docker.com/
- Кластер Kubernetes
Вы можете выбрать либо локальный, либо удаленный кластер, но какой лучше? Упрощенные варианты, такие как k3d, работают на любом компьютере, на котором может работать Docker, поэтому для запуска локального кластера больше не требуется много оперативной памяти. Удаленный кластер также может быть очень эффективным решением, но имейте в виду, что все ваши образы Docker нужно будет выгружать и загружать для каждого изменения.
Установите k3d: https://github.com/rancher/k3d
k3d не установит kubectl (это CLI для Kubernetes), поэтому установите его отдельно отсюда: https://kubernetes.io/docs/tasks/tools / install-kubectl
- Golang
Так же вам необходимо установить на ваш компьютер Golang вместе с IDE. Go бесплатен, и вы можете скачать его для MacOS, Windows или Linux по следующей ссылке: https://golang.org/dl
- IDE
Я бы порекомендовал использовать Visual Studio Code, она бесплатно и имеет набор плагинов для Go, которые вы можете добавить. Некоторые коллеги предпочитают Goland от Jetbrains. Если вы Java программист, вы, вероятно, предпочтете заплатить за Goland, поскольку он будет напоминать вам о других их продуктах.
Установите VSCode или Golang.
Создаем кластер
Вам необходимо установить все программное обеспечение, указанное в предыдущем разделе.
Создайте новый кластер с помощью k3d:
k3d create
Настройте kubectl таким образом, чтобы он указывал на новый кластер. Помните, что с одного компьютера могут использоваться несколько кластеров, поэтому крайне важно указывать на правильный:
export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
Убедитесь, что в кластере есть хотя бы один узел. Здесь вы можете видеть, что у меня установлен Kubernetes 1.17 — относительно новая версия:
kubectl get node
NAME STATUS ROLES AGE VERSION
k3d-k3s-default-server Ready master 48s v1.17.0+k3s.1
Мы будем хранить наши TODO записи в таблице базы данных, поэтому теперь нам нужно ее установить. Postgresql — это популярная реляционная база данных, которую мы можем установить в кластер с помощью диаграммы Хелма.
Установка arkade
arkade — это CLI Go, похожий на «brew» или «apt-get», но для приложений Kubernetes. Он использует Helm, kubectl или CLI проекта для установки проекта или продукта в ваш кластер.
curl -sLS https://dl.get-arkade.dev | sudo sh
Теперь установите Postgresql
arkade install postgresql
===================================================================== = PostgreSQL has been installed. =
=====================================================================
Вы также увидите информацию о строке подключения и о том, как запустить CLI Postgresql через образ Docker внутри кластера.
Вы можете получить эту информацию в любое время с помощью
arkade info postgresql
.Спроектируем схему таблицы
CREATE TABLE todo (
id INT GENERATED ALWAYS AS IDENTITY,
description text NOT NULL,
created_date timestamp NOT NULL,
completed_date timestamp NOT NULL
);
Запустите
arkade info postgresql
, чтобы снова получить информацию о соединении. Она должна выглядеть примерно так:export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode)
kubectl run postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:11.6.0-debian-9-r0 --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- psql --host postgresql -U postgres -d postgres -p 5432
Теперь у вас в командной строке есть:
postgres = #
, вы можете создать таблицу, скопировав это внутрь, затем запустите \dt
, чтобы показать таблицу:postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | todo | table | postgres
(1 row)
Установка фреймворка приложения
Так же, как PHP разработчики ускорили свой рабочий процесс с помощью LAMP (Linux Apache + Mysql + PHP) и Rails разработчики с помощью предварительно подготовленного стека, разработчики Kubernetes могут использовать фреймворки приложений.
Стек PLONK расшифровывается как Prometheus, Linux, OpenFaaS, NATS и Kubernetes.
- Prometheus предоставляет метрики, автоматическое масштабирование и наблюдаемость для проверки работоспособности вашей системы, позволяет ей реагировать на всплески спроса и сокращать расходы, предоставляя метрики для принятия решений о масштабировании до нуля.
- Linux, хотя и не единственный вариант запуска рабочих нагрузок в Kubernetes, является стандартным и наиболее простым в использовании.
- Изначально OpenFaaS предоставлял переносимые функции разработчикам, но отлично работает и при развертывании API и микросервисов. Его универсальность означает, что могут быть развернуты и управляемы любые контейнеры Docker с HTTP-сервером.
- NATS — это популярный проект CNCF, используемый для обмена сообщениями и pub/sub. В стеке PLONK он предоставляет возможность выполнять запросы асинхронно и для организации очередей.
- Kubernetes — причина, по которой мы здесь собрались. Он обеспечивает масштабируемую, самовосстанавливающуюся и декларативную инфраструктуру. И если вам не нужна больше часть всего этого великолепия, его API упрощается с помощью OpenFaaS.
Установите стек PLONK через arkade:
arkade install openfaas
Прочитайте информационное сообщение и выполните каждую команду:
- Установите faas-cli.
- Получите ваш пароль.
- Перенаправьте UI шлюза OpenFaaS (через порт 8080)
- И залогиньтесь в систему через CLI.
Как и раньше, вы можете получить информационное сообщение с помощью
аркады info openfaas
.Развертывание вашего первого API Go
Существует несколько способов создания API Go с помощью PLONK. Первый вариант — использовать Dockerfile и вручную определить TCP порт, проверку работоспособности, HTTP-сервер и так далее. Это можно сделать с помощью
faas-cli new --lang dockerfile API_NAME
, однако есть более простой и автоматизированный способ.Второй способ — воспользоваться встроенными шаблонами, предлагаемыми Function Store:
faas-cli template store list | grep go
go openfaas Classic Golang template
golang-http openfaas-incubator Golang HTTP template
golang-middleware openfaas-incubator Golang Middleware template
Поскольку мы хотим создать традиционный API в HTTP стиле, шаблон golang-middleware будет наиболее подходящим.
В начале туториала вы зарегистрировали в учетную запись Docker Hub для хранения ваших образов Docker. Каждая рабочая нагрузка в Kubernetes должна быть встроена в образ Docker, прежде чем ее можно будет развернуть.
Подтяните специальный шаблон:
faas-cli template store pull golang-middleware
Используйте Scaffold для вашего API с golang-middleware и вашим юзернеймом в Docker Hub:
export PREFIX=alexellis2
export LANG=golang-middleware
export API_NAME=todo
faas-cli new --lang $LANG --prefix $PREFIX $API_NAME
Вы увидите два сгенерированных файла:
./todo.yml
— предоставляет способ настройки, развертывания и установки шаблона и имени./todo/handler.go
— здесь вы пишете код и добавляете любые другие файлы или пакеты, которые вам требуются
Давайте проведем небольшое редактирование и затем развернем код.
package function
import (
"net/http"
"encoding/json"
)
type Todo struct {
Description string `json:"description"`
}
func Handle(w http.ResponseWriter, r *http.Request) {
todos := []Todo{}
todos = append(todos, Todo{Description: "Run faas-cli up"})
res, _ := json.Marshal(todos)
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(res))
}
Если вы не используете VScode и его плагины для редактирования и форматирования кода, то запускайте это после каждого изменения, чтобы убедиться, что файл правильно отформатирован.
gofmt -w -s ./todo/handler.go
Теперь развернем код — сначала создадим новый образ, запушим его в Docker Hub и развернем в кластере с помощью OpenFaaS API:
Invoke your endpoint when ready:
curl http://127.0.0.1:8080/function/todo
{
"description": "Run faas-cli up"
}
Разрешаем пользователям создавать новые TODO записи
Теперь разрешим пользователям создавать новые записи в своем TODO list-е. Сначала вам нужно добавить ссылку или «зависимость» для Go в библиотеку Postgresql.
Мы можем получить ее с помощью вендинга или модулей Go, которые были введены в Go 1.11 и установлены по умолчанию в Go 1.13.
Отредактируйте
handler.go
и добавьте модуль, который нам необходим для доступа к Postgresql:import (
"database/sql"
_ "github.com/lib/pq"
...
Чтобы модули Go могли обнаружить зависимость, мы должны объявить кое-что внутри файла, который мы будем использовать позже. Если мы не сделаем этого, то VSCode удалит эти строки при сохранении.
Добавьте это под импортами в файле
var db *sql.DB
Всегда запускайте эти команды в
todo
папке, где находится handler.go
, а не на корневом уровне с todo.yml
.Инициализируйте новый модуль Go:
cd todo/
ls
handler.go
export GO111MODULE=on
go mod init
Теперь обновите файл с помощью библиотеки pq:
go get
go mod tidy
cat go.mod
module github.com/alexellis/todo1/todo
go 1.13
require github.com/lib/pq v1.3.0
Что бы ни было внутри
go.mod
, скопируйте его содержимое в GO_REPLACE.txt
cat go.mod > GO_REPLACE.txt
Теперь давайте убедимся, что сборка все еще работает до добавления кода insert.
faas-cli build -f todo.yml --build-arg GO111MODULE=on
Вы можете заметить, что теперь мы передаем
--build-arg
, чтобы сообщить шаблон для использования модулей Go.Во время сборки вы увидите, что модули загружаются по мере необходимости из интернета.
Step 16/29 : RUN go test ./... -cover
---> Running in 9a4017438500
go: downloading github.com/lib/pq v1.3.0
go: extracting github.com/lib/pq v1.3.0
go: finding github.com/lib/pq v1.3.0
? github.com/alexellis/todo1/todo [no test files]
Removing intermediate container 9a4017438500
Настройка секретов для доступа к Postgresql
Мы можем создать пул соединений в
init ()
, методекоторый будет запускаться только один раз при запуске программы.// init устанавливает постоянное соединение с удаленной базой данных. Функция вызовет панику, если не сможет установить связь, и контейнер перезапустится/перейдет в цикл сбоя/возврата
func init() {
if _, err := os.Stat("/var/openfaas/secrets/password"); err == nil {
password, _ := sdk.ReadSecret("password")
user, _ := sdk.ReadSecret("username")
host, _ := sdk.ReadSecret("host")
dbName := os.Getenv("postgres_db")
port := os.Getenv("postgres_port")
sslmode := os.Getenv("postgres_sslmode")
connStr := "postgres://" + user + ":" + password + "@" + host + ":" + port + "/" + dbName + "?sslmode=" + sslmode
var err error
db, err = sql.Open("postgres", connStr)
if err != nil {
panic(err.Error())
}
err = db.Ping()
if err != nil {
panic(err.Error())
}
}
}
Как вы заметили, некоторая информация извлекается из
os.Getenv
читаемого из среды. Эти значения я бы счел неконфиденциальными, они установлены в файле todo.y
.Остальные, такие как пароль и хост, которые являются конфиденциальными, хранятся в секретах Kubernetes.
Вы можете создать их через
faas-cli secret create
или через kubectl create secret generic -n openfaas-fn
.Строка
sdk.ReadSecret
происходит из OpenFaaS Cloud SDK со следующим импортом: github.com/openfaas/openfaas-cloud/sdk
. Она читает секретный файл с диска и возвращает значение или ошибку.Получим секретные значения из
arkade info postgresql
.Теперь для каждого пароля выполним следующее:
export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode)
export USERNAME="postgres"
export PASSWORD=$POSTGRES_PASSWORD
export HOST="postgresql.default"
faas-cli secret create username --from-literal $USERNAME
faas-cli secret create password --from-literal $PASSWORD
faas-cli secret create host --from-literal $HOST
Проверим секреты на предмет наличия и соответствия:
faas-cli secret ls
NAME
username
password
host
# And via kubectl:
kubectl get secret -n openfaas-fn
NAME TYPE DATA AGE
username Opaque 1 13s
password Opaque 1 13s
host Opaque 1 12s
Отредактируем наш YAML файл и добавим следующее:
secrets:
- host
- password
- username
environment:
postgres_db: postgres
postgres_sslmode: "disable"
postgres_port: 5432
Далее обновим модули Go и снова запустим сборку:
cd todo
go get
go mod tidy
cd ..
faas-cli build -f todo.yml --build-arg GO111MODULE=on
Successfully built d2c609f8f559
Successfully tagged alexellis2/todo:latest
Image: alexellis2/todo:latest built.
[0] < Building todo done in 22.50s.
[0] Worker done.
Total build time: 22.50s
Сборка отработала как положено, поэтому запустим
faas-cli
с теми же аргументами, чтобы запушить и развернуть образ. Если учетные данные и конфигурация SQL верны, мы не увидим ошибки в логах, однако, если они неверны, мы получим код паники в init().Проверим журналы:
faas-cli logs todo
2020-03-26T14:10:03Z Forking - ./handler []
2020-03-26T14:10:03Z 2020/03/26 14:10:03 Started logging stderr from function.
2020-03-26T14:10:03Z 2020/03/26 14:10:03 Started logging stdout from function.
2020-03-26T14:10:03Z 2020/03/26 14:10:03 OperationalMode: http
2020-03-26T14:10:03Z 2020/03/26 14:10:03 Timeouts: read: 10s, write: 10s hard: 10s.
2020-03-26T14:10:03Z 2020/03/26 14:10:03 Listening on port: 8080
2020-03-26T14:10:03Z 2020/03/26 14:10:03 Metrics listening on port: 8081
2020-03-26T14:10:03Z 2020/03/26 14:10:03 Writing lock-file to: /tmp/.lock
Пока все выглядит хорошо, теперь попробуем вызвать эндпоинт:
echo | faas-cli invoke todo -f todo.yml
2020-03-26T14:11:02Z 2020/03/26 14:11:02 POST / - 200 OK - ContentLength: 35
Итак, теперь у нас установлено успешное соединение с БД, и мы можем выполнять insert. Откуда мы это знаем? Потому что
db.Ping ()
возвращает ошибку, а в противном случае пробросил бы панику:err = db.Ping()
if err != nil {
panic(err.Error())
}
Перейдите по ссылке для более подробной информации о пакете database/sql.
Пишем код insert
Этот код вставляет новую строку в таблицу
todo
и использует специальный синтаксис, в котором значение не заключено в кавычки, а вместо этого заменяется кодом db.Query. В «старые времена» LAMP программирования распространенной ошибкой, которая приводила к тому, что многие системы становились небезопасными, было отсутствие санации входных данных и конкатенация пользовательского ввода непосредственно в оператор SQL.Представьте, что кто-то введет описание;
drop table todo
, было бы не очень весело.Поэтому мы запускаем
db.Query
, затем передаем SQL инструкцию, используя $1
, $2
и т. д. для каждого значения, а затем можем получить результат и/или ошибку. Мы также должны закрыть этот результат, поэтому используйте для этого defer.func insert(description string) error {
res, err := db.Query(`insert into todo (id, description, created_date) values (DEFAULT, $1, now());`,
description)
if err != nil {
return err
}
defer res.Close()
return nil
}
Теперь давайте подключим это к коду.
func Handle(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost && r.URL.Path == "/create" {
defer r.Body.Close()
body, _ := ioutil.ReadAll(r.Body)
if err := insert(string(body)); err != nil {
http.Error(w, fmt.Sprintf("unable to insert todo: %s", err.Error()), http.StatusInternalServerError)
}
}
}
Давайте развернем это и запустим.
echo | faas-cli invoke todo -f todo.yml
curl http://127.0.0.1:8080/function/todo/create --data "faas-cli build"
curl http://127.0.0.1:8080/function/todo/create --data "faas-cli push"
curl http://127.0.0.1:8080/function/todo/create --data "faas-cli deploy"
Проверим логи API:
faas-cli logs todo
2020-03-26T14:35:29Z 2020/03/26 14:35:29 POST /create - 200 OK - ContentLength: 0
Проверим содержимое таблицы с помощью pgsql:
export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode)
kubectl run postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:11.6.0-debian-9-r0 --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- psql --host postgresql -U postgres -d postgres -p 5432
postgres=# select * from todo;
id | description | created_date | completed_date
----+-----------------+----------------------------+----------------
1 | faas-cli build | 2020-03-26 14:36:03.367789 |
2 | faas-cli push | 2020-03-26 14:36:03.389656 |
3 | faas-cli deploy | 2020-03-26 14:36:03.797881 |
Поздравляем, теперь у вас есть API TODO, которое может принимать входящие запросы через
curl
или любой другой HTTP-клиент и записывать их в таблицу базы данных.Запрос записей
Давайте создадим новую функцию для запроса TODO записей из таблицы:
func selectTodos() ([]Todo, error) {
var error err
var todos []Todo
return todos, err
}
Мы не можем назвать этот метод select, потому что это зарезервированное ключевое слово для работы с горутинами.
Теперь подключим метод к основному обработчику:
} else if r.Method == http.MethodGet && r.URL.Path == "/list" {
todos, err := selectTodos()
if err != nil {
http.Error(w, fmt.Sprintf("unable to get todos: %s", err.Error()), http.StatusInternalServerError)
}
out, _ := json.Marshal(todos)
w.Header().Set("Content-Type", "application/json")
w.Write(out)
}
Теперь, когда в нашей схеме данных есть дополнительные поля для дат, обновите структуру Todo:
type Todo struct {
ID int `json:"id"`
Description string `json:"description"`
CreatedDate *time.Time `json:"created_date"`
CompletedDate *time.Time `json:"completed_date"`
}
Теперь давайте добавим в наш метод
selectTodos()
код запроса:func selectTodos() ([]Todo, error) {
rows, getErr := db.Query(`select id, description, created_date, completed_date from todo;`)
if getErr != nil {
return []Todo{}, errors.Wrap(getErr, "unable to get from todo table")
}
todos := []Todo{}
defer rows.Close()
for rows.Next() {
result := Todo{}
scanErr := rows.Scan(&result.ID, &result.Description, &result.CreatedDate, &result.CompletedDate)
if scanErr != nil {
log.Println("scan err:", scanErr)
}
todos = append(todos, result)
}
return todos, nil
}
Как и раньше, нам нужно отложить закрытие строк для запроса. Каждое значение вставляется в новую структуру с помощью метода rows.Scan. В конце метода у нас есть кусочек содержимого Todo.
Попробуем:
faas-cli up -f todo.yml --build-arg GO111MODULE=on
curl http://127.0.0.1:8080/function/todo/list
Вот результат:
[
{
"id": 2,
"description": "faas-cli build",
"created_date": "2020-03-26T14:36:03.367789Z",
"completed_date": null
},
{
"id": 3,
"description": "faas-cli push",
"created_date": "2020-03-26T14:36:03.389656Z",
"completed_date": null
},
{
"id": 4,
"description": "faas-cli deploy",
"created_date": "2020-03-26T14:36:03.797881Z",
"completed_date": null
}
]
Чтобы удалить значения, мы можем обновить аннотации структуры, добавив
omitempty
:CompletedDate *time.Time `json:"completed_date,omitempty"`
Подытожим проделанную работу
Мы еще не закончили, но это хороший момент, чтобы остановиться и пересмотреть то, чего мы достигли на данный момент. Мы:
- Установили Go, Docker, kubectl и VSCode (IDE)
- Развернули Kubernetes на нашем локальном компьютере
- Установили Postgresql с помощью arkade и helm3
- Установили OpenFaaS и стек PLONK для разработчиков приложений Kubernetes
- Создали начальное статическое REST API с помощью Go и
golang-middleware
шаблона OpenFaaS - Добавили функциональность «insert» в наш TODO API
- Добавили функциональность «select» в наш TODO API
Полный пример кода, который мы создали до сих пор, доступен на моем GitHub акаунте: alexellis/kubernetes-todo-go-app
Дальше мы можем сделать гораздо больше, например:
- Добавление аутентификации с использованием статического токена на предъявителя
- Создание веб-страницы с использованием статического шаблона HTML или React для рендеринга TODO list-а и создания новых элементов.
- Добавление многопользовательской поддержки в API
И многое другое. Мы также могли бы покопаться в стеке PLONK и развернуть дашборд Grafana, чтобы начать наблюдать за нашим API и понять, сколько ресурсов используется с дашбордом Kubernetes или сервером метрик (установленным с помощью
arkade install
).Узнайте больше об arkade: https://get-arkade.dev
Посетите семинар OpenFaaS, чтобы подробнее изучить вышесказанное: https://github.com/openfaas/workshop/
Вы можете подписаться на мою премиальную рассылку «Insiders Updates» на
https://www.alexellis.io/
и на мой твиттер Alex Ellis
Узнать подробнее о курсе