2024 오픈소스 컨트리뷰션 아카데미 [체험형-2차] LoxiLB 로드밸런서 에 참여하여
공부하며 정리한 게시글입니다.
게시글 상 소스코드, 사진에서 **굵게** '''코드쉘''' 에 대한 부분이 들어가있을수도 있습니다.
LoxiLB 구성
- Management Plane: loxicmd, kube-loxilb
- Control Plane: API server , LoxiNLP, goBGP, netlink
- Data Plane: eBPF
Yaml 문법 설명
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
- Map
- Key, value, 공백 의 조합으로 구성
key: value
- value 가 Map 일 경우
- Key, value, 공백 의 조합으로 구성
key:
key2: value2
- Array
- value 가 여러개인경우
key:
- value1
- value2
Swagger
LoxiLB 에서 swagger 를 채택 한 이유?
→ swagger 문서 1개만으로도 여러개의 파일을 관리할 수 있다.
swagger예시: swagger.yaml
swagger: '2.0'
info:
title: Company Rest API
description: Company REST API for Baremetal Scenarios
version: 0.0.1
schemes:
- http
# - https
host: "0.0.0.0:11111"
basePath: /company_name/v1
produces:
- application/json
consumes:
- application/json
paths:
#----------------------------------------------
# Account
#----------------------------------------------
'/account':
post:
summary: Create a new account service한글도 되긴함
description: Create a new account with...
parameters:
- name: attr
in: body
required: true
description: Attributes for load balance service
schema:
$ref: '#/definitions/AccountEntry'
responses:
'200':
description: OK
schema:
$ref: '#/definitions/PostSuccess'
'400':
description: Malformed arguments for API call
schema:
$ref: '#/definitions/Error'
'/account/all':
get:
summary: Get all of user
description: Get all of the user infomation.
responses:
'200':
description: OK
schema:
type: object
properties:
Attr:
type: array
items:
$ref: '#/definitions/AccountEntry'
'401':
description: Invalid authentication credentials
schema:
$ref: '#/definitions/Error'
'500':
description: Internal service error
schema:
$ref: '#/definitions/Error'
'503':
description: Maintanence mode
schema:
$ref: '#/definitions/Error'
'/account/{user_id}':
delete:
summary: Delete one user
description: Delete one user.
parameters:
- name: user_id
in: path
type: string
required: true
description: user id
responses:
'204':
description: OK
'400':
description: Malformed arguments for API call
schema:
$ref: '#/definitions/Error'
#----------------------------------------------
# Schema definitions
#----------------------------------------------
definitions:
Error:
type: object
properties:
code:
type: integer
format: int32
sub-code:
type: integer
format: int32
message:
type: string
fields:
type: array
items:
type: string
details:
type: string
AccountEntry:
type: object
properties:
user_id:
type: string
password:
type: string
email:
type: string
PostSuccess:
type: object
properties:
code:
type: integer
message:
type: string
go mod
go mod init swaggertest
swagger 기반 환경 구성
sudo docker run --rm -it --user $(id -u):$(id -g) -e GOPATH=$(go env GOPATH):/go -v $HOME:$HOME -w $(pwd) quay.io/goswagger/swagger:0.30.3 generate server
환경 구성 진행
go mod tidy
~/ossca/examples/api ❯ tree . anaconda3 13:16:47
.
├── cmd
│ └── company-rest-api-server
**│ └── main.go**
├── go.mod
├── go.sum
├── models
│ ├── account_entry.go
│ ├── error.go
│ └── post_success.go
├── restapi
│ ├── configure_company_rest_api.go
│ ├── doc.go
│ ├── embedded_spec.go
│ ├── operations
│ │ ├── company_rest_api_api.go
│ │ ├── delete_account_user_id.go
│ │ ├── delete_account_user_id_parameters.go
│ │ ├── delete_account_user_id_responses.go
│ │ ├── delete_account_user_id_urlbuilder.go
│ │ ├── get_account_all.go
│ │ ├── get_account_all_parameters.go
│ │ ├── get_account_all_responses.go
│ │ ├── get_account_all_urlbuilder.go
│ │ ├── post_account.go
│ │ ├── post_account_parameters.go
│ │ ├── post_account_responses.go
│ │ └── post_account_urlbuilder.go
│ └── server.go
└── swagger.yaml
go build
go build cmd/company-rest-api-server/main.go
~/ossca/examples/api ❯ tree . 3s anaconda3 13:17:23
.
├── cmd
│ └── company-rest-api-server
**│ └── main.go**
├── go.mod
├── go.sum
**├── main**
├── models
│ ├── account_entry.go
│ ├── error.go
│ └── post_success.go
├── restapi
│ ├── configure_company_rest_api.go
│ ├── doc.go
│ ├── embedded_spec.go
│ ├── operations
│ │ ├── company_rest_api_api.go
│ │ ├── delete_account_user_id.go
│ │ ├── delete_account_user_id_parameters.go
│ │ ├── delete_account_user_id_responses.go
│ │ ├── delete_account_user_id_urlbuilder.go
│ │ ├── get_account_all.go
│ │ ├── get_account_all_parameters.go
│ │ ├── get_account_all_responses.go
│ │ ├── get_account_all_urlbuilder.go
│ │ ├── post_account.go
│ │ ├── post_account_parameters.go
│ │ ├── post_account_responses.go
│ │ └── post_account_urlbuilder.go
│ └── server.go
└── swagger.yaml
api test
restapi/configure_company_rest_api.go
...
api.JSONConsumer = runtime.JSONConsumer()
api.JSONProducer = runtime.JSONProducer()
if api.DeleteAccountUserIDHandler == nil {
api.DeleteAccountUserIDHandler = operations.DeleteAccountUserIDHandlerFunc(func(params operations.DeleteAccountUserIDParams) middleware.Responder {
return middleware.NotImplemented("operation operations.DeleteAccountUserID has not yet been implemented")
})
}
if api.GetAccountAllHandler == nil {
api.GetAccountAllHandler = operations.GetAccountAllHandlerFunc(func(params operations.GetAccountAllParams) middleware.Responder {
return middleware.NotImplemented("operation operations.GetAccountAll has not yet been implemented")
})
}
if api.PostAccountHandler == nil {
api.PostAccountHandler = operations.PostAccountHandlerFunc(func(params operations.PostAccountParams) middleware.Responder {
return middleware.NotImplemented("operation operations.PostAccount has not yet been implemented")
})
}
...
현재 Delete, Get, Post 에 대하여 코드선언은 되었지만, 실제 작동은 정의되지않은 상태
→ 따라서 GET 메소드를 날리면 "operation GetAccountAll has not yet been implemented”
를 응답받았음
handler 생성
mkdir restapi/handler
restapi/handler/account.go
package handler
import (
"swaggertest/models"
"swaggertest/restapi/operations"
"github.com/go-openapi/runtime/middleware"
)
func ConfigGetAccount(params operations.GetAccountAllParams) middleware.Responder {
var result []*models.AccountEntry
result = make([]*models.AccountEntry, 0)
result = append(result, &models.AccountEntry{
UserID: "idid",
Password: "passwords",
Email: "test@test.io",
})
return operations.NewGetAccountAllOK().WithPayload(&operations.GetAccountAllOKBody{Attr: result})
}
restapi/configure_company_rest_api.go 수정
if api.DeleteAccountUserIDHandler == nil {
api.DeleteAccountUserIDHandler = operations.DeleteAccountUserIDHandlerFunc(func(params operations.DeleteAccountUserIDParams) middleware.Responder {
return middleware.NotImplemented("operation operations.DeleteAccountUserID has not yet been implemented")
})
}
**api.GetAccountAllHandler = operations.GetAccountAllHandlerFunc(handler.ConfigGetAccount)**
if api.PostAccountHandler == nil {
api.PostAccountHandler = operations.PostAccountHandlerFunc(func(params operations.PostAccountParams) middleware.Responder {
return middleware.NotImplemented("operation operations.PostAccount has not yet been implemented")
})
}
다시 빌드 이후 실행
go build cmd/company-rest-api-server/main.go
curl -X 'GET' \
'http://0.0.0.0:11111/company_name/v1/account/all' \
-H 'accept: application/json'
참고로 이렇게 띄운 서버는 swagger 페이지도 뜨는데
경로는 swagger.yaml 파일에 있는
host: "0.0.0.0:11111"
basePath: /company_name/v1
를 참고해서
http://localhost:11111/company_name/v1/docs 로 접근가능하다
COBRA
Golang 기반으로 CLI 를 만드는 라이브러리
- K8s 에서 사용하기때문에, 통일성을 위해 loxilb 에서도 채택함
Command 코드 구조분석
cmd/root.go
var (
rootCmd = &cobra.Command{
Use: "cobra-cli",
Short: "A generator for Cobra based Applications",
Long: `Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}
)
...
func init() {
restOptions := &api.RESTOptions{}
rootCmd.PersistentFlags().Int16VarP(&restOptions.Timeout, "timeout", "t", 10, "Set timeout")
rootCmd.PersistentFlags().StringVarP(&restOptions.Protocol, "protocol", "", "http", "Set API server http/https")
rootCmd.PersistentFlags().StringVarP(&restOptions.PrintOption, "output", "o", "", "Set output layer (ex.) wide, json)")
rootCmd.PersistentFlags().StringVarP(&restOptions.ServerIP, "apiserver", "s", "127.0.0.1", "Set API server IP address")
rootCmd.PersistentFlags().Int16VarP(&restOptions.ServerPort, "port", "p", 11111, "Set API server port number")
rootCmd.AddCommand(create.CreateCmd())
rootCmd.AddCommand(get.GetCmd(restOptions))
}
...
CLI 로 입력할때에 사용할 옵션을 정의하는 소스코드
root.go 에서는 주로 사용할 옵션을 정의함
cmd/get/get.go
...
func GetCmd(restOptions *api.RESTOptions) *cobra.Command {
//func GetCmd() *cobra.Command {
var getCmd = &cobra.Command{
Use: "get",
Short: "get a Load balance features in the LoxiLB.",
Long: `get a Load balance features in the LoxiLB.
Create - Service type external load-balancer, Vlan, Vxlan, Qos Policies,
Endpoint client,FDB, IPaddress, Neighbor, Route,Firewall, Mirror, Session, UlCl
`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("get called!\n", args)
},
}
getCmd.AddCommand(NewGetAccountCmd(restOptions))
return getCmd
}
...
이런식으로 메소드 내부에서도 정의
Command - API 연동
tree .
.
**├── api
│ ├── account.go
│ ├── client.go
│ ├── common.go
│ └── rest.go**
├── clitest
**├── cmd
│ ├── create
│ │ └── create.go
│ ├── get
│ │ ├── get.go
│ │ └── get_account.go
│ ├── root.go
│ └── version.go**
├── go.mod
├── go.sum
└── main.go
5 directories, 13 files
- api : API호출을 위한 코드 모음
- api/rest.go: CRUD rest api 호출에 대한 부분(Get, Post, …)
- api/common.go: REST 를 command 로 호출(Create, Delete …)
- api/client.go: 특정 API 를 정의하는 부분
- api/account.go, cmd/get/get_account.go: 실제 Account 에 호출을 날리는 부분
'외부활동' 카테고리의 다른 글
[KANS3] Service (2) | 2024.09.29 |
---|---|
[KANS3] Pod & Pause container (1) | 2024.09.07 |
[KANS3] Kubernetes, kind (0) | 2024.09.07 |
[KANS3] 도커 없이 컨테이너 만들기 (5) | 2024.09.01 |
[KANS3] Docker (2) | 2024.09.01 |